• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 2009-2012 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /******************************************************************************
20  *
21  *  this file contains functions relating to BLE management.
22  *
23  ******************************************************************************/
24 
25 #include <string.h>
26 #include "bt_target.h"
27 #include "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 *******************************************************************************/
L2CA_CancelBleConnectReq(BD_ADDR rem_bda)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 *******************************************************************************/
L2CA_UpdateBleConnParams(BD_ADDR rem_bda,UINT16 min_int,UINT16 max_int,UINT16 latency,UINT16 timeout)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 *******************************************************************************/
L2CA_EnableUpdateBleConnParams(BD_ADDR rem_bda,BOOLEAN enable)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 *******************************************************************************/
L2CA_GetBleConnRole(BD_ADDR bd_addr)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 *******************************************************************************/
L2CA_GetDisconnectReason(BD_ADDR remote_bda)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 *******************************************************************************/
l2cble_scanner_conn_comp(UINT16 handle,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)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 *******************************************************************************/
l2cble_advertiser_conn_comp(UINT16 handle,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)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 *******************************************************************************/
l2cble_conn_comp(UINT16 handle,UINT8 role,BD_ADDR bda,tBLE_ADDR_TYPE type,UINT16 conn_interval,UINT16 conn_latency,UINT16 conn_timeout)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 *******************************************************************************/
l2cble_process_sig_cmd(tL2C_LCB * p_lcb,UINT8 * p,UINT16 pkt_len)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 *******************************************************************************/
l2cble_init_direct_conn(tL2C_LCB * p_lcb)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 *******************************************************************************/
l2cble_create_conn(tL2C_LCB * p_lcb)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 *******************************************************************************/
l2c_link_processs_ble_num_bufs(UINT16 num_lm_ble_bufs)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