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)
35static 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*******************************************************************************/
49BOOLEAN 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*******************************************************************************/
98BOOLEAN 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*******************************************************************************/
147BOOLEAN 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*******************************************************************************/
194UINT8 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*******************************************************************************/
214UINT16 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*******************************************************************************/
236void 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*******************************************************************************/
261void 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*******************************************************************************/
365void 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*******************************************************************************/
442void 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*******************************************************************************/
466static 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*******************************************************************************/
546void 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*******************************************************************************/
581void 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*******************************************************************************/
669BOOLEAN 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*******************************************************************************/
755BOOLEAN 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*******************************************************************************/
790void 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*******************************************************************************/
816void 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*******************************************************************************/
935void 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