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