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