Home | History | Annotate | Download | only in l2cap
      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 "l2cdefs.h"
     28 #include "l2c_int.h"
     29 #include "btu.h"
     30 #include "btm_int.h"
     31 #include "hcimsgs.h"
     32 
     33 #if (BLE_INCLUDED == TRUE)
     34 
     35 /*******************************************************************************
     36 **
     37 **  Function        L2CA_CancelBleConnectReq
     38 **
     39 **  Description     Cancel a pending connection attempt to a BLE device.
     40 **
     41 **  Parameters:     BD Address of remote
     42 **
     43 **  Return value:   TRUE if connection was cancelled
     44 **
     45 *******************************************************************************/
     46 BOOLEAN L2CA_CancelBleConnectReq (BD_ADDR rem_bda)
     47 {
     48     tL2C_LCB *p_lcb;
     49 
     50     /* There can be only one BLE connection request outstanding at a time */
     51     if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
     52     {
     53         L2CAP_TRACE_WARNING0 ("L2CA_CancelBleConnectReq - no connection pending");
     54         return(FALSE);
     55     }
     56 
     57     if (memcmp (rem_bda, l2cb.ble_connecting_bda, BD_ADDR_LEN))
     58     {
     59         L2CAP_TRACE_WARNING4 ("L2CA_CancelBleConnectReq - different  BDA Connecting: %08x%04x  Cancel: %08x%04x",
     60                               (l2cb.ble_connecting_bda[0]<<24)+(l2cb.ble_connecting_bda[1]<<16)+(l2cb.ble_connecting_bda[2]<<8)+l2cb.ble_connecting_bda[3],
     61                               (l2cb.ble_connecting_bda[4]<<8)+l2cb.ble_connecting_bda[5],
     62                               (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
     63 
     64         return(FALSE);
     65     }
     66 
     67     if (btsnd_hcic_ble_create_conn_cancel())
     68     {
     69 
     70         if ((p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda)) != NULL)
     71         {
     72             p_lcb->disc_reason = L2CAP_CONN_CANCEL;
     73             l2cu_release_lcb (p_lcb);
     74         }
     75         /* update state to be cancel, wait for connection cancel complete */
     76         btm_ble_set_conn_st (BLE_CONN_CANCEL);
     77 
     78         return(TRUE);
     79     }
     80     else
     81         return(FALSE);
     82 }
     83 
     84 /*******************************************************************************
     85 **
     86 **  Function        L2CA_InternalBleConnUpdate
     87 **
     88 **  Description     update BLE connection based on status
     89 **
     90 **  Parameters:     lcb
     91 **
     92 **  Return value:   none
     93 **
     94 *******************************************************************************/
     95 static void L2CA_InternalBleConnUpdate (tL2C_LCB *p_lcb)
     96 {
     97     if (p_lcb->upd_status & L2C_BLE_UPDATE_PENDING) return;
     98 
     99     if (p_lcb->upd_status & L2C_BLE_CONN_UPDATE_DISABLE)
    100     {
    101         /* application requests to disable parameters update.
    102            If parameters are already updated, lets set them
    103            up to what has been requested during connection establishement */
    104         if (p_lcb->upd_status & L2C_BLE_NOT_DEFAULT_PARAM)
    105         {
    106             tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
    107 
    108             btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle,
    109                 (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
    110                          p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),
    111                 (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
    112                          p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),
    113                 (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
    114                          p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF),
    115                 (UINT16)((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
    116                          p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF),
    117                 0, 0);
    118             p_lcb->upd_status &= ~L2C_BLE_NOT_DEFAULT_PARAM;
    119             p_lcb->upd_status |= (L2C_BLE_UPDATE_PENDING | L2C_BLE_NEW_CONN_PARAM);
    120         }
    121     }
    122     else
    123     {
    124         /* application allows to do update, if we were delaying one do it now */
    125         if (p_lcb->upd_status & L2C_BLE_NEW_CONN_PARAM)
    126         {
    127             btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->min_interval,
    128                 p_lcb->max_interval, p_lcb->latency, p_lcb->timeout, 0, 0);
    129             p_lcb->upd_status &= ~L2C_BLE_NEW_CONN_PARAM;
    130             p_lcb->upd_status |= (L2C_BLE_UPDATE_PENDING | L2C_BLE_NOT_DEFAULT_PARAM);
    131         }
    132     }
    133 }
    134 
    135 /*******************************************************************************
    136 **
    137 **  Function        L2CA_UpdateBleConnParams
    138 **
    139 **  Description     Update BLE connection parameters.
    140 **
    141 **  Parameters:     BD Address of remote
    142 **
    143 **  Return value:   TRUE if update started
    144 **
    145 *******************************************************************************/
    146 BOOLEAN L2CA_UpdateBleConnParams (BD_ADDR rem_bda, UINT16 min_int, UINT16 max_int, UINT16 latency, UINT16 timeout)
    147 {
    148     tL2C_LCB            *p_lcb;
    149 
    150     /* See if we have a link control block for the remote device */
    151     p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda);
    152 
    153     /* If we don't have one, create one and accept the connection. */
    154     if (!p_lcb)
    155     {
    156         L2CAP_TRACE_WARNING2 ("L2CA_UpdateBleConnParams - unknown BD_ADDR %08x%04x",
    157                               (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
    158         return(FALSE);
    159     }
    160 
    161     if (!p_lcb->is_ble_link)
    162     {
    163         L2CAP_TRACE_WARNING2 ("L2CA_UpdateBleConnParams - BD_ADDR %08x%04x not LE",
    164                               (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
    165         return(FALSE);
    166     }
    167 
    168     if (p_lcb->link_role == HCI_ROLE_MASTER)
    169     {
    170         p_lcb->min_interval = min_int;
    171         p_lcb->max_interval = max_int;
    172         p_lcb->latency = latency;
    173         p_lcb->timeout = timeout;
    174         p_lcb->upd_status |= L2C_BLE_NEW_CONN_PARAM;
    175         L2CA_InternalBleConnUpdate(p_lcb);
    176     }
    177     else
    178         l2cu_send_peer_ble_par_req (p_lcb, min_int, max_int, latency, timeout);
    179 
    180     return(TRUE);
    181 }
    182 
    183 
    184 /*******************************************************************************
    185 **
    186 **  Function        L2CA_EnableUpdateBleConnParams
    187 **
    188 **  Description     Enable or disable update based on the request from the peer
    189 **
    190 **  Parameters:     BD Address of remote
    191 **
    192 **  Return value:   TRUE if update started
    193 **
    194 *******************************************************************************/
    195 BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
    196 {
    197     tL2C_LCB            *p_lcb;
    198 
    199     /* See if we have a link control block for the remote device */
    200     p_lcb = l2cu_find_lcb_by_bd_addr (rem_bda);
    201 
    202     /* If we don't have one, create one and accept the connection. */
    203     if (!p_lcb)
    204     {
    205         L2CAP_TRACE_WARNING2 ("L2CA_EnableUpdateBleConnParams - unknown BD_ADDR %08x%04x",
    206             (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5]);
    207         return (FALSE);
    208     }
    209 
    210     L2CAP_TRACE_API4 ("L2CA_EnableUpdateBleConnParams - BD_ADDR %08x%04x enable %d upd state %d",
    211         (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5],
    212         enable, p_lcb->upd_status);
    213 
    214     if (!p_lcb->is_ble_link || (p_lcb->link_role != HCI_ROLE_MASTER))
    215     {
    216         L2CAP_TRACE_WARNING3 ("L2CA_EnableUpdateBleConnParams - BD_ADDR %08x%04x not LE or not master %d",
    217                               (rem_bda[0]<<24)+(rem_bda[1]<<16)+(rem_bda[2]<<8)+rem_bda[3], (rem_bda[4]<<8)+rem_bda[5], p_lcb->link_role);
    218         return (FALSE);
    219     }
    220 
    221     if (enable)
    222     {
    223         p_lcb->upd_status &= ~L2C_BLE_CONN_UPDATE_DISABLE;
    224     }
    225     else
    226     {
    227         p_lcb->upd_status |= L2C_BLE_CONN_UPDATE_DISABLE;
    228     }
    229 
    230     L2CA_InternalBleConnUpdate(p_lcb);
    231 
    232     return (TRUE);
    233 }
    234 
    235 /*******************************************************************************
    236 **
    237 ** Function         L2CA_HandleConnUpdateEvent
    238 **
    239 ** Description      This function enables the connection update request from remote
    240 **                  after a successful connection update response is received.
    241 **
    242 ** Returns          void
    243 **
    244 *******************************************************************************/
    245 void L2CA_HandleConnUpdateEvent (UINT16 handle, UINT8 status)
    246 {
    247     tL2C_LCB *p_lcb;
    248 
    249     L2CAP_TRACE_DEBUG0("L2CA_HandleConnUpdateEvent");
    250 
    251     /* See if we have a link control block for the remote device */
    252     p_lcb = l2cu_find_lcb_by_handle(handle);
    253     if (!p_lcb)
    254     {
    255         L2CAP_TRACE_WARNING1("L2CA_EnableUpdateBleConnParams: Invalid handle: %d", handle);
    256         return;
    257     }
    258 
    259     p_lcb->upd_status &= ~L2C_BLE_UPDATE_PENDING;
    260 
    261     if (status != HCI_SUCCESS)
    262     {
    263         L2CAP_TRACE_WARNING1("L2CA_EnableUpdateBleConnParams: Error status: %d", status);
    264     }
    265 
    266     L2CA_InternalBleConnUpdate(p_lcb);
    267 
    268     L2CAP_TRACE_DEBUG1("L2CA_HandleConnUpdateEvent: upd_status=%d", p_lcb->upd_status);
    269 }
    270 
    271 /*******************************************************************************
    272 **
    273 ** Function         L2CA_GetBleConnRole
    274 **
    275 ** Description      This function returns the connection role.
    276 **
    277 ** Returns          link role.
    278 **
    279 *******************************************************************************/
    280 UINT8 L2CA_GetBleConnRole (BD_ADDR bd_addr)
    281 {
    282     UINT8       role = HCI_ROLE_UNKNOWN;
    283 
    284     tL2C_LCB *p_lcb;
    285 
    286     if ((p_lcb = l2cu_find_lcb_by_bd_addr (bd_addr)) != NULL)
    287         role = p_lcb->link_role;
    288 
    289     return role;
    290 }
    291 /*******************************************************************************
    292 **
    293 ** Function         L2CA_GetDisconnectReason
    294 **
    295 ** Description      This function returns the disconnect reason code.
    296 **
    297 ** Returns          disconnect reason
    298 **
    299 *******************************************************************************/
    300 UINT16 L2CA_GetDisconnectReason (BD_ADDR remote_bda)
    301 {
    302     tL2C_LCB            *p_lcb;
    303     UINT16              reason = 0;
    304 
    305     if ((p_lcb = l2cu_find_lcb_by_bd_addr (remote_bda)) != NULL)
    306         reason = p_lcb->disc_reason;
    307 
    308     L2CAP_TRACE_DEBUG1 ("L2CA_GetDisconnectReason=%d ",reason);
    309 
    310     return reason;
    311 }
    312 
    313 /*******************************************************************************
    314 **
    315 ** Function         l2cble_scanner_conn_comp
    316 **
    317 ** Description      This function is called when an HCI Connection Complete
    318 **                  event is received while we are a scanner (so we are master).
    319 **
    320 ** Returns          void
    321 **
    322 *******************************************************************************/
    323 void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
    324                                UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
    325 {
    326     tL2C_LCB            *p_lcb;
    327     tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (bda);
    328 
    329     L2CAP_TRACE_DEBUG5 ("l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d slave_latency=%d supervision_tout=%d",
    330                         handle,  type, conn_interval, conn_latency, conn_timeout);
    331 
    332     l2cb.is_ble_connecting = FALSE;
    333 
    334     /* See if we have a link control block for the remote device */
    335     p_lcb = l2cu_find_lcb_by_bd_addr (bda);
    336 
    337     /* If we don't have one, create one. this is auto connection complete. */
    338     if (!p_lcb)
    339     {
    340         p_lcb = l2cu_allocate_lcb (bda, FALSE);
    341         if (!p_lcb)
    342         {
    343             btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
    344             L2CAP_TRACE_ERROR0 ("l2cble_scanner_conn_comp - failed to allocate LCB");
    345             return;
    346         }
    347         else
    348         {
    349             if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
    350             {
    351                 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
    352                 L2CAP_TRACE_WARNING0 ("l2cble_scanner_conn_comp - LCB but no CCB");
    353                 return ;
    354             }
    355         }
    356     }
    357     else if (p_lcb->link_state != LST_CONNECTING)
    358     {
    359         L2CAP_TRACE_ERROR1 ("L2CAP got BLE scanner conn_comp in bad state: %d", p_lcb->link_state);
    360         return;
    361     }
    362     btu_stop_timer(&p_lcb->timer_entry);
    363 
    364     /* Save the handle */
    365     p_lcb->handle = handle;
    366 
    367     /* Connected OK. Change state to connected, we were scanning so we are master */
    368     p_lcb->link_state = LST_CONNECTED;
    369     p_lcb->link_role  = HCI_ROLE_MASTER;
    370     p_lcb->is_ble_link = TRUE;
    371 
    372     /* If there are any preferred connection parameters, set them now */
    373     if ( (p_dev_rec->conn_params.min_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
    374          (p_dev_rec->conn_params.min_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
    375          (p_dev_rec->conn_params.max_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
    376          (p_dev_rec->conn_params.max_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
    377          (p_dev_rec->conn_params.slave_latency    <= BTM_BLE_CONN_LATENCY_MAX ) &&
    378          (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
    379          (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
    380          ((conn_interval < p_dev_rec->conn_params.min_conn_int &&
    381           p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
    382           (conn_interval > p_dev_rec->conn_params.max_conn_int) ||
    383           (conn_latency > p_dev_rec->conn_params.slave_latency) ||
    384           (conn_timeout > p_dev_rec->conn_params.supervision_tout)))
    385     {
    386         L2CAP_TRACE_ERROR5 ("upd_ll_conn_params: HANDLE=%d min_conn_int=%d max_conn_int=%d slave_latency=%d supervision_tout=%d",
    387                             handle, p_dev_rec->conn_params.min_conn_int, p_dev_rec->conn_params.max_conn_int,
    388                             p_dev_rec->conn_params.slave_latency, p_dev_rec->conn_params.supervision_tout);
    389 
    390         btsnd_hcic_ble_upd_ll_conn_params (handle,
    391                                            p_dev_rec->conn_params.min_conn_int,
    392                                            p_dev_rec->conn_params.max_conn_int,
    393                                            p_dev_rec->conn_params.slave_latency,
    394                                            p_dev_rec->conn_params.supervision_tout,
    395                                            0, 0);
    396         p_lcb->upd_status |= L2C_BLE_UPDATE_PENDING;
    397     }
    398 
    399     /* Tell BTM Acl management about the link */
    400     btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, TRUE);
    401 
    402     if (p_lcb->p_echo_rsp_cb)
    403     {
    404         L2CAP_TRACE_ERROR0 ("l2cu_send_peer_echo_req");
    405         l2cu_send_peer_echo_req (p_lcb, NULL, 0);
    406     }
    407 
    408     p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
    409 
    410     l2cu_process_fixed_chnl_resp (p_lcb);
    411 }
    412 
    413 
    414 /*******************************************************************************
    415 **
    416 ** Function         l2cble_advertiser_conn_comp
    417 **
    418 ** Description      This function is called when an HCI Connection Complete
    419 **                  event is received while we are an advertiser (so we are slave).
    420 **
    421 ** Returns          void
    422 **
    423 *******************************************************************************/
    424 void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
    425                                   UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
    426 {
    427     tL2C_LCB            *p_lcb;
    428     tBTM_SEC_DEV_REC    *p_dev_rec;
    429 
    430     /* See if we have a link control block for the remote device */
    431     p_lcb = l2cu_find_lcb_by_bd_addr (bda);
    432 
    433     /* If we don't have one, create one and accept the connection. */
    434     if (!p_lcb)
    435     {
    436         p_lcb = l2cu_allocate_lcb (bda, FALSE);
    437         if (!p_lcb)
    438         {
    439             btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
    440             L2CAP_TRACE_ERROR0 ("l2cble_advertiser_conn_comp - failed to allocate LCB");
    441             return;
    442         }
    443         else
    444         {
    445             if (!l2cu_initialize_fixed_ccb (p_lcb, L2CAP_ATT_CID, &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL].fixed_chnl_opts))
    446             {
    447                 btm_sec_disconnect (handle, HCI_ERR_NO_CONNECTION);
    448                 L2CAP_TRACE_WARNING0 ("l2cble_scanner_conn_comp - LCB but no CCB");
    449                 return ;
    450             }
    451         }
    452     }
    453 
    454     /* Save the handle */
    455     p_lcb->handle = handle;
    456 
    457     /* Connected OK. Change state to connected, we were advertising, so we are slave */
    458     p_lcb->link_state = LST_CONNECTED;
    459     p_lcb->link_role  = HCI_ROLE_SLAVE;
    460     p_lcb->is_ble_link = TRUE;
    461 
    462     /* Tell BTM Acl management about the link */
    463     p_dev_rec = btm_find_or_alloc_dev (bda);
    464 
    465     btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, TRUE);
    466 
    467     p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
    468 
    469     l2cu_process_fixed_chnl_resp (p_lcb);
    470 }
    471 
    472 /*******************************************************************************
    473 **
    474 ** Function         l2cble_conn_comp
    475 **
    476 ** Description      This function is called when an HCI Connection Complete
    477 **                  event is received.
    478 **
    479 ** Returns          void
    480 **
    481 *******************************************************************************/
    482 void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
    483                       UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
    484 {
    485     if (role == HCI_ROLE_MASTER)
    486     {
    487         l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
    488     }
    489     else
    490     {
    491         l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
    492     }
    493 }
    494 /*******************************************************************************
    495 **
    496 ** Function         l2cble_process_sig_cmd
    497 **
    498 ** Description      This function is called when a signalling packet is received
    499 **                  on the BLE signalling CID
    500 **
    501 ** Returns          void
    502 **
    503 *******************************************************************************/
    504 void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
    505 {
    506     UINT8           *p_pkt_end;
    507     UINT8           cmd_code, id;
    508     UINT16          cmd_len, rej_reason;
    509     UINT16          result;
    510     UINT16          min_interval, max_interval, latency, timeout;
    511 
    512     p_pkt_end = p + pkt_len;
    513 
    514     STREAM_TO_UINT8  (cmd_code, p);
    515     STREAM_TO_UINT8  (id, p);
    516     STREAM_TO_UINT16 (cmd_len, p);
    517 
    518     /* Check command length does not exceed packet length */
    519     if ((p + cmd_len) > p_pkt_end)
    520     {
    521         L2CAP_TRACE_WARNING3 ("L2CAP - LE - format error, pkt_len: %d  cmd_len: %d  code: %d", pkt_len, cmd_len, cmd_code);
    522         return;
    523     }
    524 
    525     switch (cmd_code)
    526     {
    527         case L2CAP_CMD_REJECT:
    528         case L2CAP_CMD_ECHO_RSP:
    529         case L2CAP_CMD_INFO_RSP:
    530             STREAM_TO_UINT16 (rej_reason, p);
    531             break;
    532         case L2CAP_CMD_ECHO_REQ:
    533         case L2CAP_CMD_INFO_REQ:
    534             l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
    535             break;
    536 
    537         case L2CAP_CMD_BLE_UPDATE_REQ:
    538             STREAM_TO_UINT16 (min_interval, p); /* 0x0006 - 0x0C80 */
    539             STREAM_TO_UINT16 (max_interval, p); /* 0x0006 - 0x0C80 */
    540             STREAM_TO_UINT16 (latency, p);  /* 0x0000 - 0x03E8 */
    541             STREAM_TO_UINT16 (timeout, p);  /* 0x000A - 0x0C80 */
    542             /* If we are a master, the slave wants to update the parameters */
    543             if (p_lcb->link_role == HCI_ROLE_MASTER)
    544             {
    545                 if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
    546                     max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
    547                     latency  > BTM_BLE_CONN_LATENCY_MAX ||
    548                     /*(timeout >= max_interval && latency > (timeout * 10/(max_interval * 1.25) - 1)) ||*/
    549                     timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
    550                     max_interval < min_interval)
    551                 {
    552                     l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
    553                 }
    554                 else
    555                 {
    556 
    557                     l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_OK, id);
    558 
    559                     p_lcb->min_interval = min_interval;
    560                     p_lcb->max_interval = max_interval;
    561                     p_lcb->latency = latency;
    562                     p_lcb->timeout = timeout;
    563                     p_lcb->upd_status |= L2C_BLE_NEW_CONN_PARAM;
    564                     L2CA_InternalBleConnUpdate(p_lcb);
    565                 }
    566             }
    567             else
    568                 l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
    569             break;
    570 
    571         case L2CAP_CMD_BLE_UPDATE_RSP:
    572             STREAM_TO_UINT16 (result, p);
    573             break;
    574 
    575         default:
    576             L2CAP_TRACE_WARNING1 ("L2CAP - LE - unknown cmd code: %d", cmd_code);
    577             l2cu_send_peer_cmd_reject (p_lcb, L2CAP_CMD_REJ_NOT_UNDERSTOOD, id, 0, 0);
    578             return;
    579     }
    580 }
    581 
    582 
    583 /*******************************************************************************
    584 **
    585 ** Function         l2cble_init_direct_conn
    586 **
    587 ** Description      This function is to initate a direct connection
    588 **
    589 ** Returns          TRUE connection initiated, FALSE otherwise.
    590 **
    591 *******************************************************************************/
    592 BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
    593 {
    594     tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
    595     tBTM_BLE_CB         *p_cb = &btm_cb.ble_ctr_cb;
    596     UINT16               scan_int, scan_win;
    597     BD_ADDR         init_addr;
    598     UINT8           init_addr_type = BLE_ADDR_PUBLIC,
    599                     own_addr_type = BLE_ADDR_PUBLIC;
    600 
    601     /* There can be only one BLE connection request outstanding at a time */
    602     if (p_dev_rec == NULL)
    603     {
    604         BTM_TRACE_WARNING0 ("unknown device, can not initate connection");
    605         return(FALSE);
    606     }
    607 
    608     scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
    609     scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
    610 
    611     init_addr_type = p_lcb->ble_addr_type;
    612     memcpy(init_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
    613 
    614     if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
    615                                         scan_win, /* UINT16 scan_win      */
    616                                         FALSE,                   /* UINT8 white_list     */
    617                                         init_addr_type,          /* UINT8 addr_type_peer */
    618                                         init_addr,               /* BD_ADDR bda_peer     */
    619                                         own_addr_type,         /* UINT8 addr_type_own  */
    620         (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
    621         p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),  /* conn_int_min  */
    622         (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ?
    623         p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),  /* conn_int_max  */
    624         (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ?
    625         p_dev_rec->conn_params.slave_latency : 0), /* UINT16 conn_latency  */
    626         (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
    627         p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_SUP_TOUT_DEF), /* conn_timeout */
    628                                         0,                       /* UINT16 min_len       */
    629                                         0))                      /* UINT16 max_len       */
    630     {
    631         l2cu_release_lcb (p_lcb);
    632         L2CAP_TRACE_ERROR0("initate direct connection fail, no resources");
    633         return (FALSE);
    634     }
    635     else
    636     {
    637         p_lcb->link_state = LST_CONNECTING;
    638         l2cb.is_ble_connecting = TRUE;
    639         memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
    640         btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
    641         btm_ble_set_conn_st (BLE_DIR_CONN);
    642 
    643         return (TRUE);
    644     }
    645 }
    646 
    647 /*******************************************************************************
    648 **
    649 ** Function         l2cble_create_conn
    650 **
    651 ** Description      This function initiates an acl connection via HCI
    652 **
    653 ** Returns          TRUE if successful, FALSE if connection not started.
    654 **
    655 *******************************************************************************/
    656 BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
    657 {
    658     tBTM_BLE_CONN_ST     conn_st = btm_ble_get_conn_st();
    659     BOOLEAN         rt = FALSE;
    660 
    661     /* There can be only one BLE connection request outstanding at a time */
    662     if (conn_st == BLE_CONN_IDLE)
    663     {
    664         rt = l2cble_init_direct_conn(p_lcb);
    665     }
    666     else
    667     {
    668         L2CAP_TRACE_WARNING1 ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
    669 
    670         btm_ble_enqueue_direct_conn_req(p_lcb);
    671 
    672         if (conn_st == BLE_BG_CONN)
    673             btm_ble_suspend_bg_conn();
    674 
    675         rt = TRUE;
    676     }
    677     return rt;
    678 }
    679 
    680 /*******************************************************************************
    681 **
    682 ** Function         l2c_link_processs_ble_num_bufs
    683 **
    684 ** Description      This function is called when a "controller buffer size"
    685 **                  event is first received from the controller. It updates
    686 **                  the L2CAP values.
    687 **
    688 ** Returns          void
    689 **
    690 *******************************************************************************/
    691 void l2c_link_processs_ble_num_bufs (UINT16 num_lm_ble_bufs)
    692 {
    693     if (num_lm_ble_bufs == 0)
    694     {
    695         num_lm_ble_bufs = L2C_DEF_NUM_BLE_BUF_SHARED;
    696         l2cb.num_lm_acl_bufs -= L2C_DEF_NUM_BLE_BUF_SHARED;
    697     }
    698 
    699     l2cb.num_lm_ble_bufs = l2cb.controller_le_xmit_window = num_lm_ble_bufs;
    700 }
    701 
    702 #endif /* (BLE_INCLUDED == TRUE) */
    703