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