l2c_ble.c revision 847b706a9cfba9dc749240b33276a7e02df30f29
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#define L2CA_GET_UPD_ST(x)          ((x) & UPD_ST_MASK)
36#define L2CA_SET_UPD_ST(x, y)      x = (((x) & ~UPD_ST_MASK) | (y))
37
38
39#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
40#include "vendor_ble.h"
41#endif
42/*******************************************************************************
43**
44**  Function        L2CA_CancelBleConnectReq
45**
46**  Description     Cancel a pending connection attempt to a BLE device.
47**
48**  Parameters:     BD Address of remote
49**
50**  Return value:   TRUE if connection was cancelled
51**
52*******************************************************************************/
53BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
54{
55    tL2C_LCB *p_lcb;
56
57    /* There can be only one BLE connection request outstanding at a time */
58    if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
59    {
60        L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - no connection pending");
61        return(FALSE);
62    }
63
64    if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN))
65    {
66        L2CAP_TRACE_WARNING ("L2CA_CancelBleConnectReq - different  BDA Connecting: %08x%04x  Cancel: %08x%04x",
67                              (l2cb.ble_connecting_bda[0]<<24)+(l2cb.ble_connecting_bda[1]<<16)+(l2cb.ble_connecting_bda[2]<<8)+l2cb.ble_connecting_bda[3],
68                              (l2cb.ble_connecting_bda[4]<<8)+l2cb.ble_connecting_bda[5],
69                              (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
70
71        return(FALSE);
72    }
73
74    if (btsnd_hcic_ble_create_conn_cancel())
75    {
76
77        if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE)) != NULL)
78        {
79            p_lcb->disc_reason = L2CAP_CONN_CANCEL;
80            l2cu_release_lcb (p_lcb);
81        }
82        /* update state to be cancel, wait for connection cancel complete */
83        btm_ble_set_conn_st (BLE_CONN_CANCEL);
84
85        return(TRUE);
86    }
87    else
88        return(FALSE);
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*******************************************************************************/
102BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int,
103                                            UINT16 latency, UINT16 timeout)
104{
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        {
114            L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
115                                  (rem_bda[0]<<24)+(rem_bda[1]<<16)+(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        {
122            L2CAP_TRACE_WARNING ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
123                                  (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
124                                  (rem_bda[4]<<8)+rem_bda[5]);
125            return(FALSE);
126        }
127#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
128        /* if both 4.1 compliant */
129        if ((HCI_LE_CONN_PARAM_REQ_SUPPORTED(btm_cb.devcb.local_le_features) &&
130         HCI_LE_CONN_PARAM_REQ_SUPPORTED(p_acl_cb->peer_le_features)))
131        {
132            /* TODO: CE length selection ?? */
133            btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_int, max_int,
134            latency, timeout, 0, 0);
135        }
136        else
137        /* if either side does not support Connection Parameters Request
138        Link Layer Control Procedure,
139           use Link Layer Connection Update procedure */
140#endif
141        {
142            if (p_lcb->link_role == HCI_ROLE_MASTER)
143                btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_int, max_int,
144                latency, timeout, 0, 0);
145            else
146                l2cu_send_peer_ble_par_req (p_lcb, min_int, max_int, latency, timeout);
147        }
148        return(TRUE);
149
150}
151
152
153/*******************************************************************************
154**
155**  Function        L2CA_EnableUpdateBleConnParams
156**
157**  Description     Enable or disable update based on the request from the peer
158**
159**  Parameters:     BD Address of remote
160**
161**  Return value:   TRUE if update started
162**
163*******************************************************************************/
164BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
165{
166    tL2C_LCB            *p_lcb;
167
168    /* See if we have a link control block for the remote device */
169    p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda, BT_TRANSPORT_LE);
170
171    if (!p_lcb)
172    {
173        L2CAP_TRACE_WARNING ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x",
174            (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
175            (rem_bda[4]<<8)+rem_bda[5]);
176        return (FALSE);
177    }
178
179    L2CAP_TRACE_API ("%s - BD_ADDR %08x%04x enable %d current upd state 0x%02x",__FUNCTION__,
180        (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
181        (rem_bda[4]<<8)+rem_bda[5], enable, p_lcb->conn_update_mask);
182
183    if (p_lcb->transport != BT_TRANSPORT_LE || (p_lcb->link_role != HCI_ROLE_MASTER))
184    {
185        L2CAP_TRACE_WARNING ("%s - BD_ADDR %08x%04x not LE or not master %d", __FUNCTION__,
186                              (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3],
187                              (rem_bda[4]<<8)+rem_bda[5], p_lcb->link_role);
188        return (FALSE);
189    }
190
191    if (enable)
192    {
193        if (L2CA_GET_UPD_ST (p_lcb->conn_update_mask) == UPD_DISABLED)
194        {
195            p_lcb->conn_param_enb.param = (TIMER_PARAM_TYPE)p_lcb;
196            btu_start_timer (&p_lcb->conn_param_enb, BTU_TTYPE_L2CAP_END_CONN_UPD,
197                                                    L2CAP_BLE_ENB_CONN_PARAM_TOUT);
198            L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_ENB_TOUT);
199        }
200    }
201    else if (L2CA_GET_UPD_ST (p_lcb->conn_update_mask) != UPD_DISABLED)
202    {
203        btu_stop_timer(&p_lcb->conn_param_enb);
204
205        if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED)
206        {
207
208            /*
209            application requests to disable parameters update.If parameters are already updated,
210            lets set them   up to what has been requested during connection establishement
211            */
212            if ((p_lcb->conn_update_mask & UPD_REQUEST) != 0)
213            {
214                /* revert back to default */
215                btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
216                                                   BTM_BLE_CONN_INT_MIN_DEF,
217                                                   BTM_BLE_CONN_INT_MAX_DEF,
218                                                   BTM_BLE_CONN_SLAVE_LATENCY_DEF,
219                                                   BTM_BLE_CONN_TIMEOUT_DEF,
220                                                   0, 0);
221            }
222        }
223        L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_DISABLED);
224
225    }
226
227    return (TRUE);
228
229}
230
231
232/*******************************************************************************
233**
234** Function         L2CA_GetBleConnRole
235**
236** Description      This function returns the connection role.
237**
238** Returns          link role.
239**
240*******************************************************************************/
241UINT8 L2CA_GetBleConnRole (BD_ADDR bd_addr)
242{
243    UINT8       role = HCI_ROLE_UNKNOWN;
244
245    tL2C_LCB *p_lcb;
246
247    if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr, BT_TRANSPORT_LE)) != NULL)
248        role = p_lcb->link_role;
249
250    return role;
251}
252/*******************************************************************************
253**
254** Function         L2CA_GetDisconnectReason
255**
256** Description      This function returns the disconnect reason code.
257**
258** Returns          disconnect reason
259**
260*******************************************************************************/
261UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda, tBT_TRANSPORT transport)
262{
263    tL2C_LCB            *p_lcb;
264    UINT16              reason = 0;
265
266    if ((p_lcb = l2cu_find_lcb_by_bd_addr (remote_bda, transport)) != NULL)
267        reason = p_lcb->disc_reason;
268
269    L2CAP_TRACE_DEBUG ("L2CA_GetDisconnectReason=%d ",reason);
270
271    return reason;
272}
273
274/*******************************************************************************
275**
276** Function         l2cble_scanner_conn_comp
277**
278** Description      This function is called when an HCI Connection Complete
279**                  event is received while we are a scanner (so we are master).
280**
281** Returns          void
282**
283*******************************************************************************/
284void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
285                               UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
286{
287    tL2C_LCB            *p_lcb;
288    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (bda);
289
290    L2CAP_TRACE_DEBUG ("l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d slave_latency=%d supervision_tout=%d",
291                        handle,  type, conn_interval, conn_latency, conn_timeout);
292
293    l2cb.is_ble_connecting = FALSE;
294
295    /* See if we have a link control block for the remote device */
296    p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
297
298    /* If we don't have one, create one. this is auto connection complete. */
299    if (!p_lcb)
300    {
301        p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
302        if (!p_lcb)
303        {
304            btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
305            L2CAP_TRACE_ERROR ("l2cble_scanner_conn_comp - failed to allocate LCB");
306            return;
307        }
308        else
309        {
310            if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
311            {
312                btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
313                L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
314                return ;
315            }
316        }
317    }
318    else if (p_lcb->link_state != LST_CONNECTING)
319    {
320        L2CAP_TRACE_ERROR ("L2CAP got BLE scanner conn_comp in bad state: %d", p_lcb->link_state);
321        return;
322    }
323    btu_stop_timer(&p_lcb->timer_entry);
324
325    /* Save the handle */
326    p_lcb->handle = handle;
327
328    /* Connected OK. Change state to connected, we were scanning so we are master */
329    p_lcb->link_state = LST_CONNECTED;
330    p_lcb->link_role  = HCI_ROLE_MASTER;
331    p_lcb->transport  = BT_TRANSPORT_LE;
332
333    /* If there are any preferred connection parameters, set them now */
334    if ( (p_dev_rec->conn_params.min_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
335         (p_dev_rec->conn_params.min_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
336         (p_dev_rec->conn_params.max_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
337         (p_dev_rec->conn_params.max_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
338         (p_dev_rec->conn_params.slave_latency    <= BTM_BLE_CONN_LATENCY_MAX ) &&
339         (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
340         (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
341         ((conn_interval < p_dev_rec->conn_params.min_conn_int &&
342          p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
343          (conn_interval > p_dev_rec->conn_params.max_conn_int) ||
344          (conn_latency > p_dev_rec->conn_params.slave_latency) ||
345          (conn_timeout > p_dev_rec->conn_params.supervision_tout)))
346    {
347        L2CAP_TRACE_ERROR ("upd_ll_conn_params: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d",
348                            handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int,
349                            p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout);
350
351        btsnd_hcic_ble_upd_ll_conn_params (handle,
352                                           p_dev_rec->conn_params.min_conn_int,
353                                           p_dev_rec->conn_params.max_conn_int,
354                                           p_dev_rec->conn_params.slave_latency,
355                                           p_dev_rec->conn_params.supervision_tout,
356                                           0, 0);
357    }
358
359    /* Tell BTM Acl management about the link */
360    btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
361
362    p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
363
364    l2cu_process_fixed_chnl_resp (p_lcb);
365
366    btm_ble_set_conn_st(BLE_CONN_IDLE);
367}
368
369
370/*******************************************************************************
371**
372** Function         l2cble_advertiser_conn_comp
373**
374** Description      This function is called when an HCI Connection Complete
375**                  event is received while we are an advertiser (so we are slave).
376**
377** Returns          void
378**
379*******************************************************************************/
380void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
381                                  UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
382{
383    tL2C_LCB            *p_lcb;
384    tBTM_SEC_DEV_REC    *p_dev_rec;
385    UNUSED(type);
386    UNUSED(conn_interval);
387    UNUSED(conn_latency);
388    UNUSED(conn_timeout);
389
390    /* See if we have a link control block for the remote device */
391    p_lcb = l2cu_find_lcb_by_bd_addr (bda, BT_TRANSPORT_LE);
392
393    /* If we don't have one, create one and accept the connection. */
394    if (!p_lcb)
395    {
396        p_lcb = l2cu_allocate_lcb (bda, FALSE, BT_TRANSPORT_LE);
397        if (!p_lcb)
398        {
399            btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
400            L2CAP_TRACE_ERROR ("l2cble_advertiser_conn_comp - failed to allocate LCB");
401            return;
402        }
403        else
404        {
405            if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
406            {
407                btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
408                L2CAP_TRACE_WARNING ("l2cble_scanner_conn_comp - LCB but no CCB");
409                return ;
410            }
411        }
412    }
413
414    /* Save the handle */
415    p_lcb->handle = handle;
416
417    /* Connected OK. Change state to connected, we were advertising, so we are slave */
418    p_lcb->link_state = LST_CONNECTED;
419    p_lcb->link_role  = HCI_ROLE_SLAVE;
420    p_lcb->transport  = BT_TRANSPORT_LE;
421
422    /* Tell BTM Acl management about the link */
423    p_dev_rec = btm_find_or_alloc_dev (bda);
424
425    btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, BT_TRANSPORT_LE);
426
427    p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
428
429    l2cu_process_fixed_chnl_resp (p_lcb);
430
431    /* when adv and initiating are both active, cancel the direct connection */
432    if (l2cb.is_ble_connecting && memcmp(bda, l2cb.ble_connecting_bda, BD_ADDR_LEN) == 0)
433    {
434        L2CA_CancelBleConnectReq(bda);
435    }
436}
437
438/*******************************************************************************
439**
440** Function         l2cble_conn_comp
441**
442** Description      This function is called when an HCI Connection Complete
443**                  event is received.
444**
445** Returns          void
446**
447*******************************************************************************/
448void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
449                      UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
450{
451    if (role == HCI_ROLE_MASTER)
452    {
453        l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
454    }
455    else
456    {
457        l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
458    }
459}
460/*******************************************************************************
461**
462** Function         l2cble_process_sig_cmd
463**
464** Description      This function is called when a signalling packet is received
465**                  on the BLE signalling CID
466**
467** Returns          void
468**
469*******************************************************************************/
470void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
471{
472    UINT8           *p_pkt_end;
473    UINT8           cmd_code, id;
474    UINT16          cmd_len, rej_reason;
475    UINT16          result;
476    UINT16          min_interval, max_interval, latency, timeout;
477
478    p_pkt_end = p + pkt_len;
479
480    STREAM_TO_UINT8  (cmd_code, p);
481    STREAM_TO_UINT8  (id, p);
482    STREAM_TO_UINT16 (cmd_len, p);
483
484    /* Check command length does not exceed packet length */
485    if ((p + cmd_len) > p_pkt_end)
486    {
487        L2CAP_TRACE_WARNING ("L2CAP - LE - format error, pkt_len: %d  cmd_len: %d  code: %d", pkt_len, cmd_len, cmd_code);
488        return;
489    }
490
491    switch (cmd_code)
492    {
493        case L2CAP_CMD_REJECT:
494        case L2CAP_CMD_ECHO_RSP:
495        case L2CAP_CMD_INFO_RSP:
496            STREAM_TO_UINT16 (rej_reason, p);
497            break;
498        case L2CAP_CMD_ECHO_REQ:
499        case L2CAP_CMD_INFO_REQ:
500            l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
501            break;
502
503        case L2CAP_CMD_BLE_UPDATE_REQ:
504            STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */
505            STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */
506            STREAM_TO_UINT16 (latency, p);  /* 0x0000 - 0x03E8 */
507            STREAM_TO_UINT16 (timeout, p);  /* 0x000A - 0x0C80 */
508            /* If we are a master, the slave wants to update the parameters */
509            if (p_lcb->link_role == HCI_ROLE_MASTER)
510            {
511                if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
512                    max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
513                    latency  > BTM_BLE_CONN_LATENCY_MAX ||
514                    /*(timeout >= max_interval && latency > (timeout * 10/(max_interval * 1.25) - 1)) ||*/
515                    timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
516                    max_interval < min_interval)
517                {
518                    l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
519                }
520                else
521                {
522
523                    l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_OK, id);
524
525                     p_lcb->min_interval = min_interval;
526                     p_lcb->max_interval = max_interval;
527                     p_lcb->latency = latency;
528                     p_lcb->timeout = timeout;
529                     p_lcb->conn_update_mask |= UPD_REQUEST;
530
531                     if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED)
532                     {
533                         btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, min_interval, max_interval,
534                                                             latency, timeout, 0, 0);
535                     }
536                     else
537                     {
538                         L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled");
539                     }
540
541                }
542            }
543            else
544                l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
545            break;
546
547        case L2CAP_CMD_BLE_UPDATE_RSP:
548            STREAM_TO_UINT16 (result, p);
549            break;
550
551        default:
552            L2CAP_TRACE_WARNING ("L2CAP - LE - unknown cmd code: %d", cmd_code);
553            l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
554            return;
555    }
556}
557/*******************************************************************************
558**
559** Function         l2c_enable_conn_param_timeout
560**
561** Description      This function process the connection parameter enabling timeout
562**
563** Returns          None.
564**
565*******************************************************************************/
566void l2c_enable_conn_param_timeout(tL2C_LCB * p_lcb)
567{
568    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
569
570
571    /* application allows to do update, if we were delaying one do it now, otherwise
572    just mark lcb that updates are enabled */
573    if (p_lcb->conn_update_mask & UPD_REQUEST)
574    {
575        btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle, p_lcb->min_interval, p_lcb->max_interval,
576                                           p_lcb->latency, p_lcb->timeout, 0, 0);
577    }
578    else
579    {
580        /* if preferred number has been set, set to preferred conn parameter */
581        if (p_dev_rec && p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF)
582        {
583            btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
584                (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
585                p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),
586                (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
587                p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),
588                (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
589                p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF),
590                (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
591                p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF),
592                0, 0);
593        }
594    }
595    L2CA_SET_UPD_ST( p_lcb->conn_update_mask, UPD_ENABLED);
596
597}
598/*******************************************************************************
599**
600** Function         l2cble_init_direct_conn
601**
602** Description      This function is to initate a direct connection
603**
604** Returns          TRUE connection initiated, FALSE otherwise.
605**
606*******************************************************************************/
607BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
608{
609    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
610    tBTM_BLE_CB         *p_cb = &btm_cb.ble_ctr_cb;
611    UINT16               scan_int, scan_win;
612    BD_ADDR         init_addr;
613    UINT8           init_addr_type = BLE_ADDR_PUBLIC,
614                    own_addr_type = BLE_ADDR_PUBLIC;
615
616    /* There can be only one BLE connection request outstanding at a time */
617    if (p_dev_rec == NULL)
618    {
619        L2CAP_TRACE_WARNING ("unknown device, can not initate connection");
620        return(FALSE);
621    }
622
623    scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
624    scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
625
626    init_addr_type = p_lcb->ble_addr_type;
627    memcpy(init_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
628
629#if BLE_PRIVACY_SPT == TRUE
630    if (p_dev_rec->ble.active_addr_type == BTM_BLE_ADDR_RRA)
631    {
632        init_addr_type = BLE_ADDR_RANDOM;
633        //memcpy(init_addr, p_dev_rec->ble.cur_rand_addr, BD_ADDR_LEN);
634    }
635    /* if privacy is on and current do not consider using reconnection address */
636    if (btm_cb.ble_ctr_cb.privacy ) /* && p_dev_rec->ble.use_reconn_addr */
637        own_addr_type = BLE_ADDR_RANDOM;
638#endif
639
640    if (!btm_ble_topology_check(BTM_BLE_STATE_INIT))
641    {
642        l2cu_release_lcb (p_lcb);
643        L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
644        return FALSE;
645    }
646#if BLE_PRIVACY_SPT == TRUE
647#if (defined BLE_VND_INCLUDED && BLE_VND_INCLUDED == TRUE)
648    extern tBTM_STATUS BTM_BleEnableIRKFeature(BOOLEAN enable);
649    if (btm_ble_vendor_irk_list_load_dev(p_dev_rec))
650        BTM_BleEnableIRKFeature(TRUE);
651
652    btm_random_pseudo_to_public(init_addr, &init_addr_type);
653#endif
654#endif
655    if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
656                                        scan_win, /* UINT16 scan_win      */
657                                        FALSE,                   /* UINT8 white_list     */
658                                        init_addr_type,          /* UINT8 addr_type_peer */
659                                        init_addr,               /* BD_ADDR bda_peer     */
660                                        own_addr_type,         /* UINT8 addr_type_own  */
661        (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
662        p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),  /* conn_int_min  */
663        (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
664        p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),  /* conn_int_max  */
665        (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
666        p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency  */
667        (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
668        p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
669                                        0,                       /* UINT16 min_len       */
670                                        0))                      /* UINT16 max_len       */
671    {
672        l2cu_release_lcb (p_lcb);
673        L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
674        return (FALSE);
675    }
676    else
677    {
678        p_lcb->link_state = LST_CONNECTING;
679        l2cb.is_ble_connecting = TRUE;
680        memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
681        btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
682        btm_ble_set_conn_st (BLE_DIR_CONN);
683
684        return (TRUE);
685    }
686}
687
688/*******************************************************************************
689**
690** Function         l2cble_create_conn
691**
692** Description      This function initiates an acl connection via HCI
693**
694** Returns          TRUE if successful, FALSE if connection not started.
695**
696*******************************************************************************/
697BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
698{
699    tBTM_BLE_CONN_ST     conn_st = btm_ble_get_conn_st();
700    BOOLEAN         rt = FALSE;
701
702    /* There can be only one BLE connection request outstanding at a time */
703    if (conn_st == BLE_CONN_IDLE)
704    {
705        rt = l2cble_init_direct_conn(p_lcb);
706    }
707    else
708    {
709        L2CAP_TRACE_WARNING ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
710
711        btm_ble_enqueue_direct_conn_req(p_lcb);
712
713        if (conn_st == BLE_BG_CONN)
714            btm_ble_suspend_bg_conn();
715
716        rt = TRUE;
717    }
718    return rt;
719}
720
721/*******************************************************************************
722**
723** Function         l2c_link_processs_ble_num_bufs
724**
725** Description      This function is called when a "controller buffer size"
726**                  event is first received from the controller. It updates
727**                  the L2CAP values.
728**
729** Returns          void
730**
731*******************************************************************************/
732void l2c_link_processs_ble_num_bufs (UINT16 num_lm_ble_bufs)
733{
734    if (num_lm_ble_bufs == 0)
735    {
736        num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED;
737        l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED;
738    }
739
740    l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs;
741}
742
743#if (defined BLE_LLT_INCLUDED) && (BLE_LLT_INCLUDED == TRUE)
744/*******************************************************************************
745**
746** Function         l2cble_process_rc_param_request_evt
747**
748** Description      process LE Remote Connection Parameter Request Event.
749**
750** Returns          void
751**
752*******************************************************************************/
753void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 int_max,
754                                     UINT16 latency, UINT16 timeout)
755{
756    tL2C_LCB    *p_lcb = l2cu_find_lcb_by_handle (handle);
757
758    if (p_lcb != NULL)
759    {
760        p_lcb->min_interval = int_min;
761        p_lcb->max_interval = int_max;
762        p_lcb->latency = latency;
763        p_lcb->timeout = timeout;
764        p_lcb->conn_update_mask |= UPD_REQUEST;
765
766        /* TODO: revisit: if update is enabled, always accept connection parameter update */
767        if (L2CA_GET_UPD_ST(p_lcb->conn_update_mask) == UPD_ENABLED)
768        {
769            btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, 0, 0);
770        }
771        else
772        {
773            L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled");
774            btsnd_hcic_ble_rc_param_req_neg_reply (handle,HCI_ERR_UNACCEPT_CONN_INTERVAL);
775        }
776
777    }
778    else
779    {
780        L2CAP_TRACE_WARNING("No link to update connection parameter")
781    }
782}
783#endif
784
785
786#endif /* (BLE_INCLUDED == TRUE) */
787