• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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,UINT16 interval,UINT16 latency,UINT16 timeout)584 void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status,
585                   UINT16 interval, UINT16 latency, UINT16 timeout)
586 {
587     L2CAP_TRACE_DEBUG("%s", __func__);
588 
589     /* See if we have a link control block for the remote device */
590     tL2C_LCB *p_lcb = l2cu_find_lcb_by_handle(handle);
591     if (!p_lcb)
592     {
593         L2CAP_TRACE_WARNING("%s: Invalid handle: %d", __func__, handle);
594         return;
595     }
596 
597     p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
598 
599     if (status != HCI_SUCCESS)
600     {
601         L2CAP_TRACE_WARNING("%s: Error status: %d", __func__, status);
602     }
603 
604     l2cble_start_conn_update(p_lcb);
605 
606     L2CAP_TRACE_DEBUG("%s: conn_update_mask=%d", __func__, p_lcb->conn_update_mask);
607 }
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