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 #include "stack_config.h"
35
36 #if (BLE_INCLUDED == TRUE)
37
38 extern fixed_queue_t *btu_general_alarm_queue;
39
40 static void l2cble_start_conn_update (tL2C_LCB *p_lcb);
41
42 /*******************************************************************************
43 **
44 ** Function L2CA_CancelBleConnectReq
45 **
46 ** Description Cancel a pending connection attempt to a BLE device.
47 **
48 ** Parameters: BD Address of remote
49 **
50 ** Return value: TRUE if connection was cancelled
51 **
52 *******************************************************************************/
L2CA_CancelBleConnectReq(BD_ADDR rem_bda)53 BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
54 {
55 tL2C_LCB *p_lcb;
56
57 /* There can be only one BLE connection request outstanding at a time */
58 if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
59 {
60 L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - no connection pending");
61 return(FALSE);
62 }
63
64 if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN))
65 {
66 L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different BDA Connecting: %08x%04x Cancel: %08x%04x",
67 (l2cb.ble_connecting_bda[0]<<24)+(l2cb.ble_connecting_bda[1]<<16)+(l2cb.ble_connecting_bda[2]<<8)+l2cb.ble_connecting_bda[3],
68 (l2cb.ble_connecting_bda[4]<<8)+l2cb.ble_connecting_bda[5],
69 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
70
71 return(FALSE);
72 }
73
74 if (btsnd_hcic_ble_create_conn_cancel())
75 {
76 p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
77 /* Do not remove lcb if an LE link is already up as a peripheral */
78 if (p_lcb != NULL &&
79 !(p_lcb->link_role == HCI_ROLE_SLAVE && BTM_ACL_IS_CONNECTED(rem_bda)))
80 {
81 p_lcb->disc_reason = L2CAP_CONN_CANCEL;
82 l2cu_release_lcb (p_lcb);
83 }
84 /* update state to be cancel, wait for connection cancel complete */
85 btm_ble_set_conn_st (BLE_CONN_CANCEL);
86
87 return(TRUE);
88 }
89 else
90 return(FALSE);
91 }
92
93 /*******************************************************************************
94 **
95 ** Function L2CA_UpdateBleConnParams
96 **
97 ** Description Update BLE connection parameters.
98 **
99 ** Parameters: BD Address of remote
100 **
101 ** Return value: TRUE if update started
102 **
103 *******************************************************************************/
L2CA_UpdateBleConnParams(BD_ADDR rem_bda,UINT16 min_int,UINT16 max_int,UINT16 latency,UINT16 timeout)104 BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int,
105 UINT16 latency, UINT16 timeout)
106 {
107 tL2C_LCB *p_lcb;
108 tACL_CONN *p_acl_cb = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
109
110 /* See if we have a link control block for the remote device */
111 p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
112
113 /* If we don't have one, create one and accept the connection. */
114 if (!p_lcb || !p_acl_cb)
115 {
116 L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
117 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
118 (rem_bda[4]<<8)+rem_bda[5]);
119 return(FALSE);
120 }
121
122 if (p_lcb->transport != BT_TRANSPORT_LE)
123 {
124 L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
125 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
126 (rem_bda[4]<<8)+rem_bda[5]);
127 return(FALSE);
128 }
129
130 p_lcb->min_interval = min_int;
131 p_lcb->max_interval = max_int;
132 p_lcb->latency = latency;
133 p_lcb->timeout = timeout;
134 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
135
136 l2cble_start_conn_update(p_lcb);
137
138 return(TRUE);
139 }
140
141
142 /*******************************************************************************
143 **
144 ** Function L2CA_EnableUpdateBleConnParams
145 **
146 ** Description Enable or disable update based on the request from the peer
147 **
148 ** Parameters: BD Address of remote
149 **
150 ** Return value: TRUE if update started
151 **
152 *******************************************************************************/
L2CA_EnableUpdateBleConnParams(BD_ADDR rem_bda,BOOLEAN enable)153 BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
154 {
155 if (stack_config_get_interface()->get_pts_conn_updates_disabled())
156 return false;
157
158 tL2C_LCB *p_lcb;
159
160 /* See if we have a link control block for the remote device */
161 p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
162
163 if (!p_lcb)
164 {
165 L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x",
166 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
167 (rem_bda[4]<<8)+rem_bda[5]);
168 return (FALSE);
169 }
170
171 L2CAP_TRACE_API ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x",__FUNCTION__,
172 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
173 (rem_bda[4]<<8)+rem_bda[5], enable, p_lcb->conn_update_mask);
174
175 if (p_lcb->transport != BT_TRANSPORT_LE)
176 {
177 L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE (link role %d)", __FUNCTION__,
178 (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
179 (rem_bda[4]<<8)+rem_bda[5], p_lcb->link_role);
180 return (FALSE);
181 }
182
183 if (enable)
184 p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
185 else
186 p_lcb->conn_update_mask |= L2C_BLE_CONN_UPDATE_DISABLE;
187
188 l2cble_start_conn_update(p_lcb);
189
190 return (TRUE);
191 }
192
193
194 /*******************************************************************************
195 **
196 ** Function L2CA_GetBleConnRole
197 **
198 ** Description This function returns the connection role.
199 **
200 ** Returns link role.
201 **
202 *******************************************************************************/
L2CA_GetBleConnRole(BD_ADDR bd_addr)203 UINT8 L2CA_GetBleConnRole (BD_ADDR bd_addr)
204 {
205 UINT8 role = HCI_ROLE_UNKNOWN;
206
207 tL2C_LCB *p_lcb;
208
209 if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_LE)) != NULL)
210 role = p_lcb->link_role;
211
212 return role;
213 }
214 /*******************************************************************************
215 **
216 ** Function L2CA_GetDisconnectReason
217 **
218 ** Description This function returns the disconnect reason code.
219 **
220 ** Returns disconnect reason
221 **
222 *******************************************************************************/
L2CA_GetDisconnectReason(BD_ADDR remote_bda,tBT_TRANSPORT transport)223 UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport)
224 {
225 tL2C_LCB *p_lcb;
226 UINT16 reason = 0;
227
228 if ((p_lcb = l2cu_find_lcb_by_bd_addr (remote_bda, transport)) != NULL)
229 reason = p_lcb->disc_reason;
230
231 L2CAP_TRACE_DEBUG ("L2CA_GetDisconnectReason=%d ",reason);
232
233 return reason;
234 }
235
l2cble_use_preferred_conn_params(BD_ADDR bda)236 void l2cble_use_preferred_conn_params(BD_ADDR bda) {
237 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
238 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda);
239
240 /* If there are any preferred connection parameters, set them now */
241 if ( (p_dev_rec->conn_params.min_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
242 (p_dev_rec->conn_params.min_conn_int <= BTM_BLE_CONN_INT_MAX ) &&
243 (p_dev_rec->conn_params.max_conn_int >= BTM_BLE_CONN_INT_MIN ) &&
244 (p_dev_rec->conn_params.max_conn_int <= BTM_BLE_CONN_INT_MAX ) &&
245 (p_dev_rec->conn_params.slave_latency <= BTM_BLE_CONN_LATENCY_MAX ) &&
246 (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
247 (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
248 ((p_lcb->min_interval < p_dev_rec->conn_params.min_conn_int &&
249 p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
250 (p_lcb->min_interval > p_dev_rec->conn_params.max_conn_int) ||
251 (p_lcb->latency > p_dev_rec->conn_params.slave_latency) ||
252 (p_lcb->timeout > p_dev_rec->conn_params.supervision_tout)))
253 {
254 L2CAP_TRACE_DEBUG ("%s: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d", __func__,
255 p_lcb->handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int,
256 p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout);
257
258 p_lcb->min_interval = p_dev_rec->conn_params.min_conn_int;
259 p_lcb->max_interval = p_dev_rec->conn_params.max_conn_int;
260 p_lcb->timeout = p_dev_rec->conn_params.supervision_tout;
261 p_lcb->latency = p_dev_rec->conn_params.slave_latency;
262
263 btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
264 p_dev_rec->conn_params.min_conn_int,
265 p_dev_rec->conn_params.max_conn_int,
266 p_dev_rec->conn_params.slave_latency,
267 p_dev_rec->conn_params.supervision_tout,
268 0, 0);
269 }
270 }
271
272 /*******************************************************************************
273 **
274 ** Function l2cble_notify_le_connection
275 **
276 ** Description This function notifiy the l2cap connection to the app layer
277 **
278 ** Returns none
279 **
280 *******************************************************************************/
l2cble_notify_le_connection(BD_ADDR bda)281 void l2cble_notify_le_connection (BD_ADDR bda)
282 {
283 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
284 tACL_CONN *p_acl = btm_bda_to_acl(bda, BT_TRANSPORT_LE) ;
285 tL2C_CCB *p_ccb;
286
287 if (p_lcb != NULL && p_acl != NULL && p_lcb->link_state != LST_CONNECTED)
288 {
289 /* update link status */
290 btm_establish_continue(p_acl);
291 /* update l2cap link status and send callback */
292 p_lcb->link_state = LST_CONNECTED;
293 l2cu_process_fixed_chnl_resp (p_lcb);
294 }
295
296 /* For all channels, send the event through their FSMs */
297 for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; p_ccb = p_ccb->p_next_ccb)
298 {
299 if (p_ccb->chnl_state == CST_CLOSED)
300 l2c_csm_execute (p_ccb, L2CEVT_LP_CONNECT_CFM, NULL);
301 }
302
303 l2cble_use_preferred_conn_params(bda);
304 }
305
306 /*******************************************************************************
307 **
308 ** Function l2cble_scanner_conn_comp
309 **
310 ** Description This function is called when an HCI Connection Complete
311 ** event is received while we are a scanner (so we are master).
312 **
313 ** Returns void
314 **
315 *******************************************************************************/
l2cble_scanner_conn_comp(UINT16 handle,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)316 void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
317 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
318 {
319 tL2C_LCB *p_lcb;
320 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (bda);
321
322 L2CAP_TRACE_DEBUG ("l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d slave_latency=%d supervision_tout=%d",
323 handle, type, conn_interval, conn_latency, conn_timeout);
324
325 l2cb.is_ble_connecting = FALSE;
326
327 /* See if we have a link control block for the remote device */
328 p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
329
330 /* If we don't have one, create one. this is auto connection complete. */
331 if (!p_lcb)
332 {
333 p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
334 if (!p_lcb)
335 {
336 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
337 L2CAP_TRACE_ERROR ("l2cble_scanner_conn_comp - failed to allocate LCB");
338 return;
339 }
340 else
341 {
342 if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
343 {
344 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
345 L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
346 return ;
347 }
348 }
349 }
350 else if (p_lcb->link_state != LST_CONNECTING)
351 {
352 L2CAP_TRACE_ERROR ("L2CAP got BLE scanner conn_comp in bad state: %d", p_lcb->link_state);
353 return;
354 }
355 alarm_cancel(p_lcb->l2c_lcb_timer);
356
357 /* Save the handle */
358 p_lcb->handle = handle;
359
360 /* Connected OK. Change state to connected, we were scanning so we are master */
361 p_lcb->link_role = HCI_ROLE_MASTER;
362 p_lcb->transport = BT_TRANSPORT_LE;
363
364 /* update link parameter, set slave link as non-spec default upon link up */
365 p_lcb->min_interval = p_lcb->max_interval = conn_interval;
366 p_lcb->timeout = conn_timeout;
367 p_lcb->latency = conn_latency;
368 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
369
370 /* Tell BTM Acl management about the link */
371 btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
372
373 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
374
375 btm_ble_set_conn_st(BLE_CONN_IDLE);
376
377 #if BLE_PRIVACY_SPT == TRUE
378 btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
379 #endif
380 }
381
382
383 /*******************************************************************************
384 **
385 ** Function l2cble_advertiser_conn_comp
386 **
387 ** Description This function is called when an HCI Connection Complete
388 ** event is received while we are an advertiser (so we are slave).
389 **
390 ** Returns void
391 **
392 *******************************************************************************/
l2cble_advertiser_conn_comp(UINT16 handle,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)393 void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
394 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
395 {
396 tL2C_LCB *p_lcb;
397 tBTM_SEC_DEV_REC *p_dev_rec;
398 UNUSED(type);
399 UNUSED(conn_interval);
400 UNUSED(conn_latency);
401 UNUSED(conn_timeout);
402
403 /* See if we have a link control block for the remote device */
404 p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
405
406 /* If we don't have one, create one and accept the connection. */
407 if (!p_lcb)
408 {
409 p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
410 if (!p_lcb)
411 {
412 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
413 L2CAP_TRACE_ERROR ("l2cble_advertiser_conn_comp - failed to allocate LCB");
414 return;
415 }
416 else
417 {
418 if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
419 {
420 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
421 L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
422 return ;
423 }
424 }
425 }
426
427 /* Save the handle */
428 p_lcb->handle = handle;
429
430 /* Connected OK. Change state to connected, we were advertising, so we are slave */
431 p_lcb->link_role = HCI_ROLE_SLAVE;
432 p_lcb->transport = BT_TRANSPORT_LE;
433
434 /* update link parameter, set slave link as non-spec default upon link up */
435 p_lcb->min_interval = p_lcb->max_interval = conn_interval;
436 p_lcb->timeout = conn_timeout;
437 p_lcb->latency = conn_latency;
438 p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
439
440 /* Tell BTM Acl management about the link */
441 p_dev_rec = btm_find_or_alloc_dev (bda);
442
443 btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
444
445 #if BLE_PRIVACY_SPT == TRUE
446 btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, TRUE);
447 #endif
448
449 p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
450
451 if (!HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(controller_get_interface()->get_features_ble()->as_array))
452 {
453 p_lcb->link_state = LST_CONNECTED;
454 l2cu_process_fixed_chnl_resp (p_lcb);
455 }
456
457 /* when adv and initiating are both active, cancel the direct connection */
458 if (l2cb.is_ble_connecting && memcmp(bda, l2cb.ble_connecting_bda, BD_ADDR_LEN) == 0)
459 {
460 L2CA_CancelBleConnectReq(bda);
461 }
462 }
463
464 /*******************************************************************************
465 **
466 ** Function l2cble_conn_comp
467 **
468 ** Description This function is called when an HCI Connection Complete
469 ** event is received.
470 **
471 ** Returns void
472 **
473 *******************************************************************************/
l2cble_conn_comp(UINT16 handle,UINT8 role,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)474 void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
475 UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
476 {
477 btm_ble_update_link_topology_mask(role, TRUE);
478
479 if (role == HCI_ROLE_MASTER)
480 {
481 l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
482 }
483 else
484 {
485 l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
486 }
487 }
488
489 /*******************************************************************************
490 **
491 ** Function l2cble_start_conn_update
492 **
493 ** Description start BLE connection parameter update process based on status
494 **
495 ** Parameters: lcb : l2cap link control block
496 **
497 ** Return value: none
498 **
499 *******************************************************************************/
l2cble_start_conn_update(tL2C_LCB * p_lcb)500 static void l2cble_start_conn_update (tL2C_LCB *p_lcb)
501 {
502 UINT16 min_conn_int, max_conn_int, slave_latency, supervision_tout;
503 tACL_CONN *p_acl_cb = btm_bda_to_acl(p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
504
505 // TODO(armansito): The return value of this call wasn't being used but the
506 // logic of this function might be depending on its side effects. We should
507 // verify if this call is needed at all and remove it otherwise.
508 btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
509
510 if (p_lcb->conn_update_mask & L2C_BLE_UPDATE_PENDING) return;
511
512 if (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE)
513 {
514 /* application requests to disable parameters update.
515 If parameters are already updated, lets set them
516 up to what has been requested during connection establishement */
517 if (p_lcb->conn_update_mask & L2C_BLE_NOT_DEFAULT_PARAM &&
518 /* current connection interval is greater than default min */
519 p_lcb->min_interval > BTM_BLE_CONN_INT_MIN)
520 {
521 /* use 7.5 ms as fast connection parameter, 0 slave latency */
522 min_conn_int = max_conn_int = BTM_BLE_CONN_INT_MIN;
523 slave_latency = BTM_BLE_CONN_SLAVE_LATENCY_DEF;
524 supervision_tout = BTM_BLE_CONN_TIMEOUT_DEF;
525
526 /* if both side 4.1, or we are master device, send HCI command */
527 if (p_lcb->link_role == HCI_ROLE_MASTER
528 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
529 || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) &&
530 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
531 #endif
532 )
533 {
534 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, min_conn_int, max_conn_int,
535 slave_latency, supervision_tout, 0, 0);
536 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
537 }
538 else
539 {
540 l2cu_send_peer_ble_par_req (p_lcb, min_conn_int, max_conn_int, slave_latency, supervision_tout);
541 }
542 p_lcb->conn_update_mask &= ~L2C_BLE_NOT_DEFAULT_PARAM;
543 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
544 }
545 }
546 else
547 {
548 /* application allows to do update, if we were delaying one do it now */
549 if (p_lcb->conn_update_mask & L2C_BLE_NEW_CONN_PARAM)
550 {
551 /* if both side 4.1, or we are master device, send HCI command */
552 if (p_lcb->link_role == HCI_ROLE_MASTER
553 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
554 || (HCI_LE_CONN_PARAM_REQ_SUPPORTED(controller_get_interface()->get_features_ble()->as_array) &&
555 HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features))
556 #endif
557 )
558 {
559 btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
560 p_lcb->max_interval, p_lcb->latency, p_lcb->timeout, 0, 0);
561 p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
562 }
563 else
564 {
565 l2cu_send_peer_ble_par_req (p_lcb, p_lcb->min_interval, p_lcb->max_interval,
566 p_lcb->latency, p_lcb->timeout);
567 }
568 p_lcb->conn_update_mask &= ~L2C_BLE_NEW_CONN_PARAM;
569 p_lcb->conn_update_mask |= L2C_BLE_NOT_DEFAULT_PARAM;
570 }
571 }
572 }
573
574 /*******************************************************************************
575 **
576 ** Function l2cble_process_conn_update_evt
577 **
578 ** Description This function enables the connection update request from remote
579 ** after a successful connection update response is received.
580 **
581 ** Returns void
582 **
583 *******************************************************************************/
l2cble_process_conn_update_evt(UINT16 handle,UINT8 status)584 void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status)
585 {
586 tL2C_LCB *p_lcb;
587
588 L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt");
589
590 /* See if we have a link control block for the remote device */
591 p_lcb = l2cu_find_lcb_by_handle(handle);
592 if (!p_lcb)
593 {
594 L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Invalid handle: %d", handle);
595 return;
596 }
597
598 p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
599
600 if (status != HCI_SUCCESS)
601 {
602 L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Error status: %d", status);
603 }
604
605 l2cble_start_conn_update(p_lcb);
606
607 L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt: conn_update_mask=%d", p_lcb->conn_update_mask);
608 }
609 /*******************************************************************************
610 **
611 ** Function l2cble_process_sig_cmd
612 **
613 ** Description This function is called when a signalling packet is received
614 ** on the BLE signalling CID
615 **
616 ** Returns void
617 **
618 *******************************************************************************/
l2cble_process_sig_cmd(tL2C_LCB * p_lcb,UINT8 * p,UINT16 pkt_len)619 void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
620 {
621 UINT8 *p_pkt_end;
622 UINT8 cmd_code, id;
623 UINT16 cmd_len;
624 UINT16 min_interval, max_interval, latency, timeout;
625 tL2C_CONN_INFO con_info;
626 UINT16 lcid = 0, rcid = 0, mtu = 0, mps = 0, initial_credit = 0;
627 tL2C_CCB *p_ccb = NULL, *temp_p_ccb = NULL;
628 tL2C_RCB *p_rcb;
629 UINT16 credit;
630 p_pkt_end = p + pkt_len;
631
632 STREAM_TO_UINT8 (cmd_code, p);
633 STREAM_TO_UINT8 (id, p);
634 STREAM_TO_UINT16 (cmd_len, p);
635
636 /* Check command length does not exceed packet length */
637 if ((p + cmd_len) > p_pkt_end)
638 {
639 L2CAP_TRACE_WARNING ("L2CAP - LE - format error, pkt_len: %d cmd_len: %d code: %d", pkt_len, cmd_len, cmd_code);
640 return;
641 }
642
643 switch (cmd_code)
644 {
645 case L2CAP_CMD_REJECT:
646 p += 2;
647 break;
648
649 case L2CAP_CMD_ECHO_REQ:
650 case L2CAP_CMD_ECHO_RSP:
651 case L2CAP_CMD_INFO_RSP:
652 case L2CAP_CMD_INFO_REQ:
653 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
654 break;
655
656 case L2CAP_CMD_BLE_UPDATE_REQ:
657 STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */
658 STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */
659 STREAM_TO_UINT16 (latency, p); /* 0x0000 - 0x03E8 */
660 STREAM_TO_UINT16 (timeout, p); /* 0x000A - 0x0C80 */
661 /* If we are a master, the slave wants to update the parameters */
662 if (p_lcb->link_role == HCI_ROLE_MASTER)
663 {
664 if (min_interval < BTM_BLE_CONN_INT_MIN_LIMIT)
665 min_interval = BTM_BLE_CONN_INT_MIN_LIMIT;
666
667 if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
668 max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
669 latency > BTM_BLE_CONN_LATENCY_MAX ||
670 /*(timeout >= max_interval && latency > (timeout * 10/(max_interval * 1.25) - 1)) ||*/
671 timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
672 max_interval < min_interval)
673 {
674 l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
675 }
676 else
677 {
678
679 l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_OK, id);
680
681 p_lcb->min_interval = min_interval;
682 p_lcb->max_interval = max_interval;
683 p_lcb->latency = latency;
684 p_lcb->timeout = timeout;
685 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
686
687 l2cble_start_conn_update(p_lcb);
688 }
689 }
690 else
691 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
692 break;
693
694 case L2CAP_CMD_BLE_UPDATE_RSP:
695 p += 2;
696 break;
697
698 case L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ:
699 STREAM_TO_UINT16 (con_info.psm, p);
700 STREAM_TO_UINT16 (rcid, p);
701 STREAM_TO_UINT16 (mtu, p);
702 STREAM_TO_UINT16 (mps, p);
703 STREAM_TO_UINT16 (initial_credit, p);
704
705 L2CAP_TRACE_DEBUG ("Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_REQ with "
706 "mtu = %d, "
707 "mps = %d, "
708 "initial credit = %d", mtu, mps, initial_credit);
709
710 if ((p_rcb = l2cu_find_ble_rcb_by_psm (con_info.psm)) == NULL)
711 {
712 L2CAP_TRACE_WARNING ("L2CAP - rcvd conn req for unknown PSM: 0x%04x", con_info.psm);
713 l2cu_reject_ble_connection (p_lcb, id, L2CAP_LE_NO_PSM);
714 break;
715 }
716 else
717 {
718 if (!p_rcb->api.pL2CA_ConnectInd_Cb)
719 {
720 L2CAP_TRACE_WARNING ("L2CAP - rcvd conn req for outgoing-only connection PSM: %d", con_info.psm);
721 l2cu_reject_ble_connection (p_lcb, id, L2CAP_CONN_NO_PSM);
722 break;
723 }
724 }
725
726 /* Allocate a ccb for this.*/
727 if ((p_ccb = l2cu_allocate_ccb (p_lcb, 0)) == NULL)
728 {
729 L2CAP_TRACE_ERROR ("L2CAP - unable to allocate CCB");
730 l2cu_reject_ble_connection (p_lcb, id, L2CAP_CONN_NO_RESOURCES);
731 break;
732 }
733
734 /* validate the parameters */
735 if (mtu < L2CAP_LE_MIN_MTU || mps < L2CAP_LE_MIN_MPS || mps > L2CAP_LE_MAX_MPS)
736 {
737 L2CAP_TRACE_ERROR ("L2CAP don't like the params");
738 l2cu_reject_ble_connection (p_lcb, id, L2CAP_CONN_NO_RESOURCES);
739 break;
740 }
741
742 p_ccb->remote_id = id;
743 p_ccb->p_rcb = p_rcb;
744 p_ccb->remote_cid = rcid;
745
746 p_ccb->peer_conn_cfg.mtu = mtu;
747 p_ccb->peer_conn_cfg.mps = mps;
748 p_ccb->peer_conn_cfg.credits = initial_credit;
749
750 p_ccb->tx_mps = mps;
751 p_ccb->ble_sdu = NULL;
752 p_ccb->ble_sdu_length = 0;
753 p_ccb->is_first_seg = TRUE;
754 p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
755
756 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info);
757 break;
758
759 case L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES:
760 L2CAP_TRACE_DEBUG ("Recv L2CAP_CMD_BLE_CREDIT_BASED_CONN_RES");
761 /* For all channels, see whose identifier matches this id */
762 for (temp_p_ccb = p_lcb->ccb_queue.p_first_ccb; temp_p_ccb; temp_p_ccb = temp_p_ccb->p_next_ccb)
763 {
764 if (temp_p_ccb->local_id == id)
765 {
766 p_ccb = temp_p_ccb;
767 break;
768 }
769 }
770 if (p_ccb)
771 {
772 L2CAP_TRACE_DEBUG ("I remember the connection req");
773 STREAM_TO_UINT16 (p_ccb->remote_cid, p);
774 STREAM_TO_UINT16 (p_ccb->peer_conn_cfg.mtu, p);
775 STREAM_TO_UINT16 (p_ccb->peer_conn_cfg.mps, p);
776 STREAM_TO_UINT16 (p_ccb->peer_conn_cfg.credits, p);
777 STREAM_TO_UINT16 (con_info.l2cap_result, p);
778 con_info.remote_cid = p_ccb->remote_cid;
779
780 L2CAP_TRACE_DEBUG ("remote_cid = %d, "
781 "mtu = %d, "
782 "mps = %d, "
783 "initial_credit = %d, "
784 "con_info.l2cap_result = %d",
785 p_ccb->remote_cid, p_ccb->peer_conn_cfg.mtu, p_ccb->peer_conn_cfg.mps,
786 p_ccb->peer_conn_cfg.credits, con_info.l2cap_result);
787
788 /* validate the parameters */
789 if (p_ccb->peer_conn_cfg.mtu < L2CAP_LE_MIN_MTU ||
790 p_ccb->peer_conn_cfg.mps < L2CAP_LE_MIN_MPS ||
791 p_ccb->peer_conn_cfg.mps > L2CAP_LE_MAX_MPS)
792 {
793 L2CAP_TRACE_ERROR ("L2CAP don't like the params");
794 con_info.l2cap_result = L2CAP_LE_NO_RESOURCES;
795 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
796 break;
797 }
798
799 p_ccb->tx_mps = p_ccb->peer_conn_cfg.mps;
800 p_ccb->ble_sdu = NULL;
801 p_ccb->ble_sdu_length = 0;
802 p_ccb->is_first_seg = TRUE;
803 p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
804
805 if (con_info.l2cap_result == L2CAP_LE_CONN_OK)
806 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP, &con_info);
807 else
808 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
809 }
810 else
811 {
812 L2CAP_TRACE_DEBUG ("I DO NOT remember the connection req");
813 con_info.l2cap_result = L2CAP_LE_INVALID_SOURCE_CID;
814 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
815 }
816 break;
817
818 case L2CAP_CMD_BLE_FLOW_CTRL_CREDIT:
819 STREAM_TO_UINT16(lcid, p);
820 if((p_ccb = l2cu_find_ccb_by_remote_cid(p_lcb, lcid)) == NULL)
821 {
822 L2CAP_TRACE_DEBUG ("%s Credit received for unknown channel id %d", __func__, lcid);
823 break;
824 }
825
826 STREAM_TO_UINT16(credit ,p);
827 l2c_csm_execute(p_ccb, L2CEVT_L2CAP_RECV_FLOW_CONTROL_CREDIT, &credit);
828 L2CAP_TRACE_DEBUG ("%s Credit received", __func__);
829 break;
830
831 case L2CAP_CMD_DISC_REQ:
832 STREAM_TO_UINT16 (lcid, p);
833 STREAM_TO_UINT16 (rcid, p);
834
835 if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) != NULL)
836 {
837 if (p_ccb->remote_cid == rcid)
838 {
839 p_ccb->remote_id = id;
840 l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DISCONNECT_REQ, NULL);
841 }
842 }
843 else
844 l2cu_send_peer_disc_rsp (p_lcb, id, lcid, rcid);
845
846 break;
847
848 case L2CAP_CMD_DISC_RSP:
849 STREAM_TO_UINT16 (rcid, p);
850 STREAM_TO_UINT16 (lcid, p);
851
852 if ((p_ccb = l2cu_find_ccb_by_cid (p_lcb, lcid)) != NULL)
853 {
854 if ((p_ccb->remote_cid == rcid) && (p_ccb->local_id == id))
855 l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DISCONNECT_RSP, NULL);
856 }
857 break;
858
859 default:
860 L2CAP_TRACE_WARNING ("L2CAP - LE - unknown cmd code: %d", cmd_code);
861 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
862 break;
863 }
864 }
865
866 /*******************************************************************************
867 **
868 ** Function l2cble_init_direct_conn
869 **
870 ** Description This function is to initate a direct connection
871 **
872 ** Returns TRUE connection initiated, FALSE otherwise.
873 **
874 *******************************************************************************/
l2cble_init_direct_conn(tL2C_LCB * p_lcb)875 BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
876 {
877 tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
878 tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
879 UINT16 scan_int;
880 UINT16 scan_win;
881 BD_ADDR peer_addr;
882 UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
883 UINT8 own_addr_type = BLE_ADDR_PUBLIC;
884
885 /* There can be only one BLE connection request outstanding at a time */
886 if (p_dev_rec == NULL)
887 {
888 L2CAP_TRACE_WARNING ("unknown device, can not initate connection");
889 return(FALSE);
890 }
891
892 scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
893 scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
894
895 peer_addr_type = p_lcb->ble_addr_type;
896 memcpy(peer_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
897
898 #if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE))
899 own_addr_type = btm_cb.ble_ctr_cb.privacy_mode ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC;
900 if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT)
901 {
902 if (btm_cb.ble_ctr_cb.privacy_mode >= BTM_PRIVACY_1_2)
903 own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
904
905 btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
906 btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type);
907 } else {
908 btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, TRUE);
909
910 // If we have a current RPA, use that instead.
911 if (!bdaddr_is_empty((const bt_bdaddr_t *)p_dev_rec->ble.cur_rand_addr)) {
912 memcpy(peer_addr, p_dev_rec->ble.cur_rand_addr, BD_ADDR_LEN);
913 }
914 }
915 #endif
916
917 if (!btm_ble_topology_check(BTM_BLE_STATE_INIT))
918 {
919 l2cu_release_lcb (p_lcb);
920 L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
921 return FALSE;
922 }
923
924 if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */
925 scan_win, /* UINT16 scan_win */
926 FALSE, /* UINT8 white_list */
927 peer_addr_type, /* UINT8 addr_type_peer */
928 peer_addr, /* BD_ADDR bda_peer */
929 own_addr_type, /* UINT8 addr_type_own */
930 (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
931 p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF), /* UINT16 conn_int_min */
932 (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
933 p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF), /* UINT16 conn_int_max */
934 (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
935 p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency */
936 (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
937 p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
938 0, /* UINT16 min_len */
939 0)) /* UINT16 max_len */
940 {
941 l2cu_release_lcb (p_lcb);
942 L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
943 return (FALSE);
944 }
945 else
946 {
947 p_lcb->link_state = LST_CONNECTING;
948 l2cb.is_ble_connecting = TRUE;
949 memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
950 alarm_set_on_queue(p_lcb->l2c_lcb_timer,
951 L2CAP_BLE_LINK_CONNECT_TIMEOUT_MS,
952 l2c_lcb_timer_timeout, p_lcb,
953 btu_general_alarm_queue);
954 btm_ble_set_conn_st (BLE_DIR_CONN);
955
956 return (TRUE);
957 }
958 }
959
960 /*******************************************************************************
961 **
962 ** Function l2cble_create_conn
963 **
964 ** Description This function initiates an acl connection via HCI
965 **
966 ** Returns TRUE if successful, FALSE if connection not started.
967 **
968 *******************************************************************************/
l2cble_create_conn(tL2C_LCB * p_lcb)969 BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
970 {
971 tBTM_BLE_CONN_ST conn_st = btm_ble_get_conn_st();
972 BOOLEAN rt = FALSE;
973
974 /* There can be only one BLE connection request outstanding at a time */
975 if (conn_st == BLE_CONN_IDLE)
976 {
977 rt = l2cble_init_direct_conn(p_lcb);
978 }
979 else
980 {
981 L2CAP_TRACE_WARNING ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
982
983 btm_ble_enqueue_direct_conn_req(p_lcb);
984
985 if (conn_st == BLE_BG_CONN)
986 btm_ble_suspend_bg_conn();
987
988 rt = TRUE;
989 }
990 return rt;
991 }
992
993 /*******************************************************************************
994 **
995 ** Function l2c_link_processs_ble_num_bufs
996 **
997 ** Description This function is called when a "controller buffer size"
998 ** event is first received from the controller. It updates
999 ** the L2CAP values.
1000 **
1001 ** Returns void
1002 **
1003 *******************************************************************************/
l2c_link_processs_ble_num_bufs(UINT16 num_lm_ble_bufs)1004 void l2c_link_processs_ble_num_bufs (UINT16 num_lm_ble_bufs)
1005 {
1006 if (num_lm_ble_bufs == 0)
1007 {
1008 num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED;
1009 l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED;
1010 }
1011
1012 l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs;
1013 }
1014
1015 /*******************************************************************************
1016 **
1017 ** Function l2c_ble_link_adjust_allocation
1018 **
1019 ** Description This function is called when a link is created or removed
1020 ** to calculate the amount of packets each link may send to
1021 ** the HCI without an ack coming back.
1022 **
1023 ** Currently, this is a simple allocation, dividing the
1024 ** number of Controller Packets by the number of links. In
1025 ** the future, QOS configuration should be examined.
1026 **
1027 ** Returns void
1028 **
1029 *******************************************************************************/
l2c_ble_link_adjust_allocation(void)1030 void l2c_ble_link_adjust_allocation (void)
1031 {
1032 UINT16 qq, yy, qq_remainder;
1033 tL2C_LCB *p_lcb;
1034 UINT16 hi_quota, low_quota;
1035 UINT16 num_lowpri_links = 0;
1036 UINT16 num_hipri_links = 0;
1037 UINT16 controller_xmit_quota = l2cb.num_lm_ble_bufs;
1038 UINT16 high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
1039
1040 /* If no links active, reset buffer quotas and controller buffers */
1041 if (l2cb.num_ble_links_active == 0)
1042 {
1043 l2cb.controller_le_xmit_window = l2cb.num_lm_ble_bufs;
1044 l2cb.ble_round_robin_quota = l2cb.ble_round_robin_unacked = 0;
1045 return;
1046 }
1047
1048 /* First, count the links */
1049 for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++)
1050 {
1051 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE)
1052 {
1053 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)
1054 num_hipri_links++;
1055 else
1056 num_lowpri_links++;
1057 }
1058 }
1059
1060 /* now adjust high priority link quota */
1061 low_quota = num_lowpri_links ? 1 : 0;
1062 while ( (num_hipri_links * high_pri_link_quota + low_quota) > controller_xmit_quota )
1063 high_pri_link_quota--;
1064
1065
1066 /* Work out the xmit quota and buffer quota high and low priorities */
1067 hi_quota = num_hipri_links * high_pri_link_quota;
1068 low_quota = (hi_quota < controller_xmit_quota) ? controller_xmit_quota - hi_quota : 1;
1069
1070 /* Work out and save the HCI xmit quota for each low priority link */
1071
1072 /* If each low priority link cannot have at least one buffer */
1073 if (num_lowpri_links > low_quota)
1074 {
1075 l2cb.ble_round_robin_quota = low_quota;
1076 qq = qq_remainder = 0;
1077 }
1078 /* If each low priority link can have at least one buffer */
1079 else if (num_lowpri_links > 0)
1080 {
1081 l2cb.ble_round_robin_quota = 0;
1082 l2cb.ble_round_robin_unacked = 0;
1083 qq = low_quota / num_lowpri_links;
1084 qq_remainder = low_quota % num_lowpri_links;
1085 }
1086 /* If no low priority link */
1087 else
1088 {
1089 l2cb.ble_round_robin_quota = 0;
1090 l2cb.ble_round_robin_unacked = 0;
1091 qq = qq_remainder = 0;
1092 }
1093 L2CAP_TRACE_EVENT ("l2c_ble_link_adjust_allocation num_hipri: %u num_lowpri: %u low_quota: %u round_robin_quota: %u qq: %u",
1094 num_hipri_links, num_lowpri_links, low_quota,
1095 l2cb.ble_round_robin_quota, qq);
1096
1097 /* Now, assign the quotas to each link */
1098 for (yy = 0, p_lcb = &l2cb.lcb_pool[0]; yy < MAX_L2CAP_LINKS; yy++, p_lcb++)
1099 {
1100 if (p_lcb->in_use && p_lcb->transport == BT_TRANSPORT_LE)
1101 {
1102 if (p_lcb->acl_priority == L2CAP_PRIORITY_HIGH)
1103 {
1104 p_lcb->link_xmit_quota = high_pri_link_quota;
1105 }
1106 else
1107 {
1108 /* Safety check in case we switched to round-robin with something outstanding */
1109 /* if sent_not_acked is added into round_robin_unacked then don't add it again */
1110 /* l2cap keeps updating sent_not_acked for exiting from round robin */
1111 if (( p_lcb->link_xmit_quota > 0 )&&( qq == 0 ))
1112 l2cb.ble_round_robin_unacked += p_lcb->sent_not_acked;
1113
1114 p_lcb->link_xmit_quota = qq;
1115 if (qq_remainder > 0)
1116 {
1117 p_lcb->link_xmit_quota++;
1118 qq_remainder--;
1119 }
1120 }
1121
1122 L2CAP_TRACE_EVENT("l2c_ble_link_adjust_allocation LCB %d Priority: %d XmitQuota: %d",
1123 yy, p_lcb->acl_priority, p_lcb->link_xmit_quota);
1124
1125 L2CAP_TRACE_EVENT(" SentNotAcked: %d RRUnacked: %d",
1126 p_lcb->sent_not_acked, l2cb.round_robin_unacked);
1127
1128 /* There is a special case where we have readjusted the link quotas and */
1129 /* this link may have sent anything but some other link sent packets so */
1130 /* so we may need a timer to kick off this link's transmissions. */
1131 if ( (p_lcb->link_state == LST_CONNECTED)
1132 && (!list_is_empty(p_lcb->link_xmit_data_q))
1133 && (p_lcb->sent_not_acked < p_lcb->link_xmit_quota) ) {
1134 alarm_set_on_queue(p_lcb->l2c_lcb_timer,
1135 L2CAP_LINK_FLOW_CONTROL_TIMEOUT_MS,
1136 l2c_lcb_timer_timeout, p_lcb,
1137 btu_general_alarm_queue);
1138 }
1139 }
1140 }
1141 }
1142
1143 #if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
1144 /*******************************************************************************
1145 **
1146 ** Function l2cble_process_rc_param_request_evt
1147 **
1148 ** Description process LE Remote Connection Parameter Request Event.
1149 **
1150 ** Returns void
1151 **
1152 *******************************************************************************/
l2cble_process_rc_param_request_evt(UINT16 handle,UINT16 int_min,UINT16 int_max,UINT16 latency,UINT16 timeout)1153 void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
1154 UINT16 latency, UINT16 timeout)
1155 {
1156 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle (handle);
1157
1158 if (p_lcb != NULL)
1159 {
1160 p_lcb->min_interval = int_min;
1161 p_lcb->max_interval = int_max;
1162 p_lcb->latency = latency;
1163 p_lcb->timeout = timeout;
1164
1165 /* if update is enabled, always accept connection parameter update */
1166 if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0)
1167 {
1168 btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, 0, 0);
1169 }
1170 else
1171 {
1172 L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled");
1173 p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
1174 btsnd_hcic_ble_rc_param_req_neg_reply (handle,HCI_ERR_UNACCEPT_CONN_INTERVAL);
1175 }
1176
1177 }
1178 else
1179 {
1180 L2CAP_TRACE_WARNING("No link to update connection parameter")
1181 }
1182 }
1183 #endif
1184
1185 /*******************************************************************************
1186 **
1187 ** Function l2cble_update_data_length
1188 **
1189 ** Description This function update link tx data length if applicable
1190 **
1191 ** Returns void
1192 **
1193 *******************************************************************************/
l2cble_update_data_length(tL2C_LCB * p_lcb)1194 void l2cble_update_data_length(tL2C_LCB *p_lcb)
1195 {
1196 UINT16 tx_mtu = 0;
1197 UINT16 i = 0;
1198
1199 L2CAP_TRACE_DEBUG("%s", __FUNCTION__);
1200
1201 /* See if we have a link control block for the connection */
1202 if (p_lcb == NULL)
1203 return;
1204
1205 for (i = 0; i < L2CAP_NUM_FIXED_CHNLS; i++)
1206 {
1207 if (i + L2CAP_FIRST_FIXED_CHNL != L2CAP_BLE_SIGNALLING_CID)
1208 {
1209 if ((p_lcb->p_fixed_ccbs[i] != NULL) &&
1210 (tx_mtu < (p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD)))
1211 tx_mtu = p_lcb->p_fixed_ccbs[i]->tx_data_len + L2CAP_PKT_OVERHEAD;
1212 }
1213 }
1214
1215 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX)
1216 tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1217
1218 /* update TX data length if changed */
1219 if (p_lcb->tx_data_len != tx_mtu)
1220 BTM_SetBleDataLength(p_lcb->remote_bd_addr, tx_mtu);
1221
1222 }
1223
1224 /*******************************************************************************
1225 **
1226 ** Function l2cble_process_data_length_change_evt
1227 **
1228 ** Description This function process the data length change event
1229 **
1230 ** Returns void
1231 **
1232 *******************************************************************************/
l2cble_process_data_length_change_event(UINT16 handle,UINT16 tx_data_len,UINT16 rx_data_len)1233 void l2cble_process_data_length_change_event(UINT16 handle, UINT16 tx_data_len, UINT16 rx_data_len)
1234 {
1235 tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
1236
1237 L2CAP_TRACE_DEBUG("%s TX data len = %d", __FUNCTION__, tx_data_len);
1238 if (p_lcb == NULL)
1239 return;
1240
1241 if (tx_data_len > 0)
1242 p_lcb->tx_data_len = tx_data_len;
1243
1244 /* ignore rx_data len for now */
1245 }
1246
1247 /*******************************************************************************
1248 **
1249 ** Function l2cble_set_fixed_channel_tx_data_length
1250 **
1251 ** Description This function update max fixed channel tx data length if applicable
1252 **
1253 ** Returns void
1254 **
1255 *******************************************************************************/
l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda,UINT16 fix_cid,UINT16 tx_mtu)1256 void l2cble_set_fixed_channel_tx_data_length(BD_ADDR remote_bda, UINT16 fix_cid, UINT16 tx_mtu)
1257 {
1258 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(remote_bda, BT_TRANSPORT_LE);
1259 UINT16 cid = fix_cid - L2CAP_FIRST_FIXED_CHNL;
1260
1261 L2CAP_TRACE_DEBUG("%s TX MTU = %d", __FUNCTION__, tx_mtu);
1262
1263 if (!controller_get_interface()->supports_ble_packet_extension())
1264 {
1265 L2CAP_TRACE_WARNING("%s, request not supported", __FUNCTION__);
1266 return;
1267 }
1268
1269 /* See if we have a link control block for the connection */
1270 if (p_lcb == NULL)
1271 return;
1272
1273 if (p_lcb->p_fixed_ccbs[cid] != NULL)
1274 {
1275 if (tx_mtu > BTM_BLE_DATA_SIZE_MAX)
1276 tx_mtu = BTM_BLE_DATA_SIZE_MAX;
1277
1278 p_lcb->p_fixed_ccbs[cid]->tx_data_len = tx_mtu;
1279 }
1280
1281 l2cble_update_data_length(p_lcb);
1282 }
1283
1284 /*******************************************************************************
1285 **
1286 ** Function l2cble_credit_based_conn_req
1287 **
1288 ** Description This function sends LE Credit Based Connection Request for
1289 ** LE connection oriented channels.
1290 **
1291 ** Returns void
1292 **
1293 *******************************************************************************/
l2cble_credit_based_conn_req(tL2C_CCB * p_ccb)1294 void l2cble_credit_based_conn_req (tL2C_CCB *p_ccb)
1295 {
1296 if (!p_ccb)
1297 return;
1298
1299 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1300 {
1301 L2CAP_TRACE_WARNING ("LE link doesn't exist");
1302 return;
1303 }
1304
1305 l2cu_send_peer_ble_credit_based_conn_req (p_ccb);
1306 return;
1307 }
1308
1309 /*******************************************************************************
1310 **
1311 ** Function l2cble_credit_based_conn_res
1312 **
1313 ** Description This function sends LE Credit Based Connection Response for
1314 ** LE connection oriented channels.
1315 **
1316 ** Returns void
1317 **
1318 *******************************************************************************/
l2cble_credit_based_conn_res(tL2C_CCB * p_ccb,UINT16 result)1319 void l2cble_credit_based_conn_res (tL2C_CCB *p_ccb, UINT16 result)
1320 {
1321 if (!p_ccb)
1322 return;
1323
1324 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1325 {
1326 L2CAP_TRACE_WARNING ("LE link doesn't exist");
1327 return;
1328 }
1329
1330 l2cu_send_peer_ble_credit_based_conn_res (p_ccb, result);
1331 return;
1332 }
1333
1334 /*******************************************************************************
1335 **
1336 ** Function l2cble_send_flow_control_credit
1337 **
1338 ** Description This function sends flow control credits for
1339 ** LE connection oriented channels.
1340 **
1341 ** Returns void
1342 **
1343 *******************************************************************************/
l2cble_send_flow_control_credit(tL2C_CCB * p_ccb,UINT16 credit_value)1344 void l2cble_send_flow_control_credit(tL2C_CCB *p_ccb, UINT16 credit_value)
1345 {
1346 if (!p_ccb)
1347 return;
1348
1349 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1350 {
1351 L2CAP_TRACE_WARNING ("LE link doesn't exist");
1352 return;
1353 }
1354
1355 l2cu_send_peer_ble_flow_control_credit(p_ccb, credit_value);
1356 return;
1357
1358 }
1359
1360 /*******************************************************************************
1361 **
1362 ** Function l2cble_send_peer_disc_req
1363 **
1364 ** Description This function sends disconnect request
1365 ** to the peer LE device
1366 **
1367 ** Returns void
1368 **
1369 *******************************************************************************/
l2cble_send_peer_disc_req(tL2C_CCB * p_ccb)1370 void l2cble_send_peer_disc_req(tL2C_CCB *p_ccb)
1371 {
1372 L2CAP_TRACE_DEBUG ("%s",__func__);
1373 if (!p_ccb)
1374 return;
1375
1376 if (p_ccb->p_lcb && p_ccb->p_lcb->transport != BT_TRANSPORT_LE)
1377 {
1378 L2CAP_TRACE_WARNING ("LE link doesn't exist");
1379 return;
1380 }
1381
1382 l2cu_send_peer_ble_credit_based_disconn_req(p_ccb);
1383 return;
1384 }
1385
1386 /*******************************************************************************
1387 **
1388 ** Function l2cble_sec_comp
1389 **
1390 ** Description This function is called when security procedure for an LE COC
1391 ** link is done
1392 **
1393 ** Returns void
1394 **
1395 *******************************************************************************/
l2cble_sec_comp(BD_ADDR p_bda,tBT_TRANSPORT transport,void * p_ref_data,UINT8 status)1396 void l2cble_sec_comp(BD_ADDR p_bda, tBT_TRANSPORT transport, void *p_ref_data, UINT8 status)
1397 {
1398 tL2C_LCB *p_lcb = l2cu_find_lcb_by_bd_addr(p_bda, BT_TRANSPORT_LE);
1399 tL2CAP_SEC_DATA *p_buf = NULL;
1400 UINT8 sec_flag;
1401 UINT8 sec_act;
1402
1403 if (!p_lcb)
1404 {
1405 L2CAP_TRACE_WARNING ("%s security complete for unknown device", __func__);
1406 return;
1407 }
1408
1409 sec_act = p_lcb->sec_act;
1410 p_lcb->sec_act = 0;
1411
1412 if (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
1413 {
1414 p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q);
1415 if (!p_buf)
1416 {
1417 L2CAP_TRACE_WARNING ("%s Security complete for request not initiated from L2CAP",
1418 __func__);
1419 return;
1420 }
1421
1422 if (status != BTM_SUCCESS)
1423 {
1424 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1425 }
1426 else
1427 {
1428 if (sec_act == BTM_SEC_ENCRYPT_MITM)
1429 {
1430 BTM_GetSecurityFlagsByTransport(p_bda, &sec_flag, transport);
1431 if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
1432 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1433 else
1434 {
1435 L2CAP_TRACE_DEBUG ("%s MITM Protection Not present", __func__);
1436 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data,
1437 BTM_FAILED_ON_SECURITY);
1438 }
1439 }
1440 else
1441 {
1442 L2CAP_TRACE_DEBUG ("%s MITM Protection not required sec_act = %d",
1443 __func__, p_lcb->sec_act);
1444
1445 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1446 }
1447 }
1448 }
1449 else
1450 {
1451 L2CAP_TRACE_WARNING ("%s Security complete for request not initiated from L2CAP", __func__);
1452 return;
1453 }
1454 osi_free(p_buf);
1455
1456 while (!fixed_queue_is_empty(p_lcb->le_sec_pending_q))
1457 {
1458 p_buf = (tL2CAP_SEC_DATA*) fixed_queue_dequeue(p_lcb->le_sec_pending_q);
1459
1460 if (status != BTM_SUCCESS)
1461 (*(p_buf->p_callback))(p_bda, BT_TRANSPORT_LE, p_buf->p_ref_data, status);
1462 else
1463 l2ble_sec_access_req(p_bda, p_buf->psm, p_buf->is_originator,
1464 p_buf->p_callback, p_buf->p_ref_data);
1465
1466 osi_free(p_buf);
1467 }
1468 }
1469
1470 /*******************************************************************************
1471 **
1472 ** Function l2ble_sec_access_req
1473 **
1474 ** Description This function is called by LE COC link to meet the
1475 ** security requirement for the link
1476 **
1477 ** Returns TRUE - security procedures are started
1478 ** FALSE - failure
1479 **
1480 *******************************************************************************/
l2ble_sec_access_req(BD_ADDR bd_addr,UINT16 psm,BOOLEAN is_originator,tL2CAP_SEC_CBACK * p_callback,void * p_ref_data)1481 BOOLEAN l2ble_sec_access_req(BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator, tL2CAP_SEC_CBACK *p_callback, void *p_ref_data)
1482 {
1483 L2CAP_TRACE_DEBUG ("%s", __func__);
1484 BOOLEAN status;
1485 tL2C_LCB *p_lcb = NULL;
1486
1487 if (!p_callback)
1488 {
1489 L2CAP_TRACE_ERROR("%s No callback function", __func__);
1490 return FALSE;
1491 }
1492
1493 p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
1494
1495 if (!p_lcb)
1496 {
1497 L2CAP_TRACE_ERROR ("%s Security check for unknown device", __func__);
1498 p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_UNKNOWN_ADDR);
1499 return FALSE;
1500 }
1501
1502 tL2CAP_SEC_DATA *p_buf = (tL2CAP_SEC_DATA*) osi_malloc((UINT16)sizeof(tL2CAP_SEC_DATA));
1503 if (!p_buf)
1504 {
1505 p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_NO_RESOURCES);
1506 return FALSE;
1507 }
1508
1509 p_buf->psm = psm;
1510 p_buf->is_originator = is_originator;
1511 p_buf->p_callback = p_callback;
1512 p_buf->p_ref_data = p_ref_data;
1513 fixed_queue_enqueue(p_lcb->le_sec_pending_q, p_buf);
1514 status = btm_ble_start_sec_check(bd_addr, psm, is_originator, &l2cble_sec_comp, p_ref_data);
1515
1516 return status;
1517 }
1518 #endif /* (BLE_INCLUDED == TRUE) */
1519