xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/controller/src/ble_ll_conn_hci.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <stdint.h>
21 #include <string.h>
22 #include <assert.h>
23 #include "syscfg/syscfg.h"
24 #include "os/os.h"
25 #include "nimble/ble.h"
26 #include "nimble/nimble_opt.h"
27 #include "nimble/hci_common.h"
28 #include "nimble/ble_hci_trans.h"
29 #include "controller/ble_ll.h"
30 #include "controller/ble_ll_hci.h"
31 #include "controller/ble_ll_conn.h"
32 #include "controller/ble_ll_ctrl.h"
33 #include "controller/ble_ll_scan.h"
34 #include "controller/ble_ll_adv.h"
35 #include "ble_ll_conn_priv.h"
36 
37 /*
38  * Used to limit the rate at which we send the number of completed packets
39  * event to the host. This is the os time at which we can send an event.
40  */
41 static ble_npl_time_t g_ble_ll_last_num_comp_pkt_evt;
42 extern uint8_t *g_ble_ll_conn_comp_ev;
43 
44 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
45 static const uint8_t ble_ll_valid_conn_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK
46 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
47                                 | BLE_HCI_LE_PHY_2M_PREF_MASK
48 #endif
49 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
50                                 | BLE_HCI_LE_PHY_CODED_PREF_MASK
51 #endif
52                               );
53 static const uint8_t ble_ll_conn_required_phy_mask = (BLE_HCI_LE_PHY_1M_PREF_MASK
54 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
55                             | BLE_HCI_LE_PHY_CODED_PREF_MASK
56 #endif
57                             );
58 #endif
59 
60 /**
61  * Allocate an event to send a connection complete event when initiating
62  *
63  * @return int 0: success -1: failure
64  */
65 static int
ble_ll_init_alloc_conn_comp_ev(void)66 ble_ll_init_alloc_conn_comp_ev(void)
67 {
68     int rc;
69     uint8_t *evbuf;
70 
71     rc = 0;
72     evbuf = g_ble_ll_conn_comp_ev;
73     if (evbuf == NULL) {
74         evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
75         if (!evbuf) {
76             rc = -1;
77         } else {
78             g_ble_ll_conn_comp_ev = evbuf;
79         }
80     }
81 
82     return rc;
83 }
84 
85 /**
86  * Called to check that the connection parameters are within range
87  *
88  * @param itvl_min
89  * @param itvl_max
90  * @param latency
91  * @param spvn_tmo
92  *
93  * @return int BLE_ERR_INV_HCI_CMD_PARMS if invalid parameters, 0 otherwise
94  */
95 int
ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min,uint16_t itvl_max,uint16_t latency,uint16_t spvn_tmo)96 ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max,
97                                 uint16_t latency, uint16_t spvn_tmo)
98 {
99     uint32_t spvn_tmo_usecs;
100     uint32_t min_spvn_tmo_usecs;
101 
102     if ((itvl_min > itvl_max) ||
103         (itvl_min < BLE_HCI_CONN_ITVL_MIN) ||
104         (itvl_max > BLE_HCI_CONN_ITVL_MAX) ||
105         (latency > BLE_HCI_CONN_LATENCY_MAX) ||
106         (spvn_tmo < BLE_HCI_CONN_SPVN_TIMEOUT_MIN) ||
107         (spvn_tmo > BLE_HCI_CONN_SPVN_TIMEOUT_MAX)) {
108         return BLE_ERR_INV_HCI_CMD_PARMS;
109     }
110 
111     /*
112     * Supervision timeout (in msecs) must be more than:
113     *  (1 + connLatency) * connIntervalMax * 1.25 msecs * 2.
114     */
115     spvn_tmo_usecs = spvn_tmo;
116     spvn_tmo_usecs *= (BLE_HCI_CONN_SPVN_TMO_UNITS * 1000);
117     min_spvn_tmo_usecs = (uint32_t)itvl_max * 2 * BLE_LL_CONN_ITVL_USECS;
118     min_spvn_tmo_usecs *= (1 + latency);
119     if (spvn_tmo_usecs <= min_spvn_tmo_usecs) {
120         return BLE_ERR_INV_HCI_CMD_PARMS;
121     }
122 
123     return BLE_ERR_SUCCESS;
124 }
125 
126 /**
127  * Send a connection complete event
128  *
129  * @param status The BLE error code associated with the event
130  */
131 void
ble_ll_conn_comp_event_send(struct ble_ll_conn_sm * connsm,uint8_t status,uint8_t * evbuf,struct ble_ll_adv_sm * advsm)132 ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
133                             uint8_t *evbuf, struct ble_ll_adv_sm *advsm)
134 {
135     uint8_t peer_addr_type;
136     uint8_t enabled;
137     uint8_t enh_enabled;
138     uint8_t *evdata;
139     uint8_t *rpa;
140 
141     enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_COMPLETE);
142     enh_enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE);
143 
144     if (enabled || enh_enabled) {
145         /* Put common elements in event */
146         evbuf[0] = BLE_HCI_EVCODE_LE_META;
147         if (enh_enabled) {
148             evbuf[1] = BLE_HCI_LE_ENH_CONN_COMPLETE_LEN;
149             evbuf[2] = BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE;
150         } else {
151             evbuf[1] = BLE_HCI_LE_CONN_COMPLETE_LEN;
152             evbuf[2] = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
153         }
154         evbuf[3] = status;
155 
156         if (connsm) {
157             put_le16(evbuf + 4, connsm->conn_handle);
158 
159             evbuf[6] = connsm->conn_role - 1;
160             peer_addr_type = connsm->peer_addr_type;
161 
162             evdata = evbuf + 14;
163             if (enh_enabled) {
164                 memset(evdata, 0, 2 * BLE_DEV_ADDR_LEN);
165                 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
166                     if (connsm->inita_identity_used) {
167                         /* If it was direct advertising we were replying to and we used
168                          * identity address there (which might be just fine), we should
169                          * we should take it into account here in this event.
170                          */
171                         rpa = NULL;
172                     } else  if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
173                         rpa = ble_ll_scan_get_local_rpa();
174                     } else {
175                         rpa = NULL;
176                     }
177                 } else {
178                     rpa = ble_ll_adv_get_local_rpa(advsm);
179                 }
180                 if (rpa) {
181                     memcpy(evdata, rpa, BLE_DEV_ADDR_LEN);
182                 }
183 
184                 /* We need to adjust peer type if device connected using RPA
185                  * and was resolved since RPA needs to be added to HCI event.
186                  */
187                  if (connsm->peer_addr_type < BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT
188                          && (connsm->rpa_index > -1)) {
189                      peer_addr_type += 2;
190                  }
191 
192                 if (peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
193                     if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
194                         rpa = ble_ll_scan_get_peer_rpa();
195                     } else {
196                         rpa = ble_ll_adv_get_peer_rpa(advsm);
197                     }
198                     memcpy(evdata + 6, rpa, BLE_DEV_ADDR_LEN);
199                 }
200                 evdata += 12;
201             } else {
202                 if (peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
203                     peer_addr_type -= 2;
204                 }
205             }
206 
207             evbuf[7] = peer_addr_type;
208             memcpy(evbuf + 8, connsm->peer_addr, BLE_DEV_ADDR_LEN);
209 
210             put_le16(evdata, connsm->conn_itvl);
211             put_le16(evdata + 2, connsm->slave_latency);
212             put_le16(evdata + 4, connsm->supervision_tmo);
213             evdata[6] = connsm->master_sca;
214         } else {
215             /* zero remaining bytes of event (2 bytes used for subevent opcode
216              * and status)
217              **/
218             memset(&evbuf[4], 0, evbuf[1] - 2);
219         }
220         ble_ll_hci_event_send(evbuf);
221     }
222 }
223 
224 
225 /**
226  * Called to create and send the number of completed packets event to the
227  * host.
228  */
229 void
ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm * connsm)230 ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm)
231 {
232     /** The maximum number of handles that will fit in an event buffer. */
233     static const int max_handles =
234         (BLE_LL_MAX_EVT_LEN - BLE_HCI_EVENT_HDR_LEN - 1) / 4;
235 
236     int event_sent;
237     uint8_t *evbuf;
238     uint8_t *handle_ptr;
239     uint8_t handles;
240 
241     if (connsm == NULL) {
242         goto skip_conn;
243     }
244 
245     /*
246      * At some periodic rate, make sure we go through all active connections
247      * and send the number of completed packet events. We do this mainly
248      * because the spec says we must update the host even though no packets
249      * have completed but there are data packets in the controller buffers
250      * (i.e. enqueued in a connection state machine).
251      */
252     if ((ble_npl_stime_t)(ble_npl_time_get() - g_ble_ll_last_num_comp_pkt_evt) <
253                                             MYNEWT_VAL(BLE_NUM_COMP_PKT_RATE)) {
254         /*
255          * If this connection has completed packets, send an event right away.
256          * We do this to increase throughput but we dont want to search the
257          * entire active list every time.
258          */
259         if (connsm->completed_pkts) {
260             evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
261             if (evbuf) {
262                 evbuf[0] = BLE_HCI_EVCODE_NUM_COMP_PKTS;
263                 evbuf[1] = (2 * sizeof(uint16_t)) + 1;
264                 evbuf[2] = 1;
265                 put_le16(evbuf + 3, connsm->conn_handle);
266                 put_le16(evbuf + 5, connsm->completed_pkts);
267                 ble_ll_hci_event_send(evbuf);
268                 connsm->completed_pkts = 0;
269             }
270         }
271         return;
272     }
273 
274     /* Iterate through all the active, created connections */
275 skip_conn:
276     evbuf = NULL;
277     handles = 0;
278     handle_ptr = NULL;
279     event_sent = 0;
280     SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) {
281         /*
282          * Only look at connections that we have sent a connection complete
283          * event and that either has packets enqueued or has completed packets.
284          */
285         if ((connsm->conn_state != BLE_LL_CONN_STATE_IDLE) &&
286             (connsm->completed_pkts || !STAILQ_EMPTY(&connsm->conn_txq))) {
287             /* If no buffer, get one, If cant get one, leave. */
288             if (!evbuf) {
289                 evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
290                 if (!evbuf) {
291                     break;
292                 }
293                 handles = 0;
294                 handle_ptr = evbuf + 3;
295             }
296 
297             /* Add handle and complete packets */
298             put_le16(handle_ptr, connsm->conn_handle);
299             put_le16(handle_ptr + 2, connsm->completed_pkts);
300             connsm->completed_pkts = 0;
301             handle_ptr += (2 * sizeof(uint16_t));
302             ++handles;
303 
304             /* Send now if the buffer is full. */
305             if (handles == max_handles) {
306                 evbuf[0] = BLE_HCI_EVCODE_NUM_COMP_PKTS;
307                 evbuf[1] = (handles * 2 * sizeof(uint16_t)) + 1;
308                 evbuf[2] = handles;
309                 ble_ll_hci_event_send(evbuf);
310                 evbuf = NULL;
311                 handles = 0;
312                 event_sent = 1;
313             }
314         }
315     }
316 
317     /* Send event if there is an event to send */
318     if (evbuf) {
319         evbuf[0] = BLE_HCI_EVCODE_NUM_COMP_PKTS;
320         evbuf[1] = (handles * 2 * sizeof(uint16_t)) + 1;
321         evbuf[2] = handles;
322         ble_ll_hci_event_send(evbuf);
323         event_sent = 1;
324     }
325 
326     if (event_sent) {
327         g_ble_ll_last_num_comp_pkt_evt = ble_npl_time_get();
328     }
329 }
330 
331 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) == 1)
332 /**
333  * Send a authenticated payload timeout event
334  *
335  * NOTE: we currently only send this event when we have a reason to send it;
336  * not when it fails.
337  *
338  * @param reason The BLE error code to send as a disconnect reason
339  */
340 void
ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm * connsm)341 ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm)
342 {
343     uint8_t *evbuf;
344 
345     if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_AUTH_PYLD_TMO)) {
346         evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
347         if (evbuf) {
348             evbuf[0] = BLE_HCI_EVCODE_AUTH_PYLD_TMO;
349             evbuf[1] = sizeof(uint16_t);
350             put_le16(evbuf + 2, connsm->conn_handle);
351             ble_ll_hci_event_send(evbuf);
352         }
353     }
354 }
355 #endif
356 
357 /**
358  * Send a disconnection complete event.
359  *
360  * NOTE: we currently only send this event when we have a reason to send it;
361  * not when it fails.
362  *
363  * @param reason The BLE error code to send as a disconnect reason
364  */
365 void
ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm * connsm,uint8_t reason)366 ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t reason)
367 {
368     uint8_t *evbuf;
369 
370     if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_DISCONN_CMP)) {
371         evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
372         if (evbuf) {
373             evbuf[0] = BLE_HCI_EVCODE_DISCONN_CMP;
374             evbuf[1] = BLE_HCI_EVENT_DISCONN_COMPLETE_LEN;
375             evbuf[2] = BLE_ERR_SUCCESS;
376             put_le16(evbuf + 3, connsm->conn_handle);
377             evbuf[5] = reason;
378             ble_ll_hci_event_send(evbuf);
379         }
380     }
381 }
382 
383 static int
ble_ll_conn_hci_chk_scan_params(uint16_t itvl,uint16_t window)384 ble_ll_conn_hci_chk_scan_params(uint16_t itvl, uint16_t window)
385 {
386     /* Check interval and window */
387     if ((itvl < BLE_HCI_SCAN_ITVL_MIN) ||
388         (itvl > BLE_HCI_SCAN_ITVL_MAX) ||
389         (window < BLE_HCI_SCAN_WINDOW_MIN) ||
390         (window > BLE_HCI_SCAN_WINDOW_MAX) ||
391         (itvl < window)) {
392         return BLE_ERR_INV_HCI_CMD_PARMS;
393     }
394 
395     return 0;
396 }
397 
398 /**
399  * Process the HCI command to create a connection.
400  *
401  * Context: Link Layer task (HCI command processing)
402  *
403  * @param cmdbuf
404  *
405  * @return int
406  */
407 int
ble_ll_conn_create(uint8_t * cmdbuf)408 ble_ll_conn_create(uint8_t *cmdbuf)
409 {
410     int rc;
411     struct hci_create_conn ccdata;
412     struct hci_create_conn *hcc;
413     struct ble_ll_conn_sm *connsm;
414 
415     /* If we are already creating a connection we should leave */
416     if (g_ble_ll_conn_create_sm) {
417         return BLE_ERR_CMD_DISALLOWED;
418     }
419 
420     /* If already enabled, we return an error */
421     if (ble_ll_scan_enabled()) {
422         return BLE_ERR_CMD_DISALLOWED;
423     }
424 
425     /* Retrieve command data */
426     hcc = &ccdata;
427     hcc->scan_itvl = get_le16(cmdbuf);
428     hcc->scan_window = get_le16(cmdbuf + 2);
429 
430     rc = ble_ll_conn_hci_chk_scan_params(hcc->scan_itvl, hcc->scan_window);
431     if (rc) {
432         return BLE_ERR_INV_HCI_CMD_PARMS;
433     }
434 
435     /* Check filter policy */
436     hcc->filter_policy = cmdbuf[4];
437     if (hcc->filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) {
438         return BLE_ERR_INV_HCI_CMD_PARMS;
439     }
440 
441     /* Get peer address type and address only if no whitelist used */
442     if (hcc->filter_policy == 0) {
443         hcc->peer_addr_type = cmdbuf[5];
444         if (hcc->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) {
445             return BLE_ERR_INV_HCI_CMD_PARMS;
446         }
447 
448         memcpy(&hcc->peer_addr, cmdbuf + 6, BLE_DEV_ADDR_LEN);
449     }
450 
451     /* Get own address type (used in connection request) */
452     hcc->own_addr_type = cmdbuf[12];
453     if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
454         return BLE_ERR_INV_HCI_CMD_PARMS;
455     }
456 
457     /* Check connection interval, latency and supervision timeoout */
458     hcc->conn_itvl_min = get_le16(cmdbuf + 13);
459     hcc->conn_itvl_max = get_le16(cmdbuf + 15);
460     hcc->conn_latency = get_le16(cmdbuf + 17);
461     hcc->supervision_timeout = get_le16(cmdbuf + 19);
462     rc = ble_ll_conn_hci_chk_conn_params(hcc->conn_itvl_min,
463                                          hcc->conn_itvl_max,
464                                          hcc->conn_latency,
465                                          hcc->supervision_timeout);
466     if (rc) {
467         return rc;
468     }
469 
470     /* Min/max connection event lengths */
471     hcc->min_ce_len = get_le16(cmdbuf + 21);
472     hcc->max_ce_len = get_le16(cmdbuf + 23);
473     if (hcc->min_ce_len > hcc->max_ce_len) {
474         return BLE_ERR_INV_HCI_CMD_PARMS;
475     }
476 
477     /* Make sure we can allocate an event to send the connection complete */
478     if (ble_ll_init_alloc_conn_comp_ev()) {
479         return BLE_ERR_MEM_CAPACITY;
480     }
481 
482     /* Make sure we can accept a connection! */
483     connsm = ble_ll_conn_sm_get();
484     if (connsm == NULL) {
485         return BLE_ERR_CONN_LIMIT;
486     }
487 
488     /* Initialize state machine in master role and start state machine */
489     ble_ll_conn_master_init(connsm, hcc);
490     ble_ll_conn_sm_new(connsm);
491     /* CSA will be selected when advertising is received */
492 
493     /* Start scanning */
494     rc = ble_ll_scan_initiator_start(hcc, &connsm->scansm);
495     if (rc) {
496         SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle);
497         STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
498     } else {
499         /* Set the connection state machine we are trying to create. */
500         g_ble_ll_conn_create_sm = connsm;
501     }
502 
503     return rc;
504 }
505 
506 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
507 static void
ble_ll_conn_init_hcc_params(struct hci_ext_create_conn * hcc,int valid_param_idx)508 ble_ll_conn_init_hcc_params(struct hci_ext_create_conn *hcc,
509                             int valid_param_idx)
510 {
511     struct hci_ext_conn_params *hcc_params = &hcc->params[valid_param_idx];
512 
513     if (valid_param_idx != 0 && !(hcc->init_phy_mask & BLE_PHY_MASK_1M)) {
514         hcc->params[0] = *hcc_params;
515     }
516 
517 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
518     if (valid_param_idx != 1 && !(hcc->init_phy_mask & BLE_PHY_MASK_2M)) {
519         hcc->params[1] = *hcc_params;
520     }
521 #endif
522 
523 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
524     if (valid_param_idx != 2 && !(hcc->init_phy_mask & BLE_PHY_MASK_CODED)) {
525         hcc->params[2] = *hcc_params;
526     }
527 #endif
528 }
529 
530 int
ble_ll_ext_conn_create(uint8_t * cmdbuf,uint8_t cmdlen)531 ble_ll_ext_conn_create(uint8_t *cmdbuf, uint8_t cmdlen)
532 {
533     int rc;
534     struct hci_ext_create_conn ccdata;
535     struct hci_ext_create_conn *hcc;
536     struct hci_ext_conn_params *hcc_params;
537     struct ble_ll_conn_sm *connsm;
538     int valid_param_idx = -1;
539     int iter;
540 
541     /* validate length */
542     if (cmdlen < 10) {
543         return BLE_ERR_INV_HCI_CMD_PARMS;
544     }
545 
546     /* If we are already creating a connection we should leave */
547     if (g_ble_ll_conn_create_sm) {
548         return BLE_ERR_CMD_DISALLOWED;
549     }
550 
551     /* If already enabled, we return an error */
552     if (ble_ll_scan_enabled()) {
553         return BLE_ERR_CMD_DISALLOWED;
554     }
555 
556     /* Retrieve command data */
557     hcc = &ccdata;
558     memset (hcc, 0, sizeof(*hcc));
559 
560     /* Check filter policy */
561     hcc->filter_policy = cmdbuf[0];
562     if (hcc->filter_policy > BLE_HCI_INITIATOR_FILT_POLICY_MAX) {
563         return BLE_ERR_INV_HCI_CMD_PARMS;
564     }
565 
566     /* Get own address type (used in connection request) */
567     hcc->own_addr_type = cmdbuf[1];
568     if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_MAX) {
569         return BLE_ERR_INV_HCI_CMD_PARMS;
570     }
571 
572     /* Get peer address type and address only if no whitelist used */
573     if (hcc->filter_policy == 0) {
574         hcc->peer_addr_type = cmdbuf[2];
575         if (hcc->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_MAX) {
576             return BLE_ERR_INV_HCI_CMD_PARMS;
577         }
578 
579         memcpy(&hcc->peer_addr, cmdbuf + 3, BLE_DEV_ADDR_LEN);
580     }
581 
582     hcc->init_phy_mask = cmdbuf[9];
583     if (hcc->init_phy_mask & ~ble_ll_valid_conn_phy_mask) {
584         return BLE_ERR_INV_HCI_CMD_PARMS;
585     }
586 
587     if (!(hcc->init_phy_mask & ble_ll_conn_required_phy_mask)) {
588         /* At least one of those need to be set */
589         return BLE_ERR_INV_HCI_CMD_PARMS;
590     }
591 
592     iter = 10;
593     if (hcc->init_phy_mask & BLE_PHY_MASK_1M) {
594         /* validate length */
595         if (cmdlen < iter + 16) {
596             return BLE_ERR_INV_HCI_CMD_PARMS;
597         }
598 
599         hcc_params = &hcc->params[0];
600         hcc_params->scan_itvl = get_le16(cmdbuf + iter);
601         hcc_params->scan_window = get_le16(cmdbuf + iter + 2);
602         iter += 4;
603 
604         rc = ble_ll_conn_hci_chk_scan_params(hcc_params->scan_itvl,
605                                              hcc_params->scan_window);
606         if (rc) {
607             return rc;
608         }
609 
610         hcc_params->conn_itvl_min = get_le16(cmdbuf + iter);
611         hcc_params->conn_itvl_max = get_le16(cmdbuf + iter + 2);
612         hcc_params->conn_latency = get_le16(cmdbuf + iter + 4);
613         hcc_params->supervision_timeout = get_le16(cmdbuf + iter + 6);
614         rc = ble_ll_conn_hci_chk_conn_params(hcc_params->conn_itvl_min,
615                                              hcc_params->conn_itvl_max,
616                                              hcc_params->conn_latency,
617                                              hcc_params->supervision_timeout);
618         if (rc) {
619             return rc;
620         }
621         iter += 8;
622 
623         /* Min/max connection event lengths */
624         hcc_params->min_ce_len = get_le16(cmdbuf + iter);
625         hcc_params->max_ce_len = get_le16(cmdbuf + iter + 2);
626         if (hcc_params->min_ce_len > hcc_params->max_ce_len) {
627             return BLE_ERR_INV_HCI_CMD_PARMS;
628         }
629 
630         iter += 4;
631         valid_param_idx = 0;
632     }
633 
634 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
635     if (hcc->init_phy_mask & BLE_PHY_MASK_2M) {
636         /* validate length */
637         if (cmdlen < iter + 16) {
638             return BLE_ERR_INV_HCI_CMD_PARMS;
639         }
640 
641         /* Move to connection parameters */
642         hcc_params = &hcc->params[1];
643         iter += 4;
644 
645         hcc_params->conn_itvl_min = get_le16(cmdbuf + iter);
646         hcc_params->conn_itvl_max = get_le16(cmdbuf + iter + 2);
647         hcc_params->conn_latency = get_le16(cmdbuf + iter + 4);
648         hcc_params->supervision_timeout = get_le16(cmdbuf + iter + 6);
649         rc = ble_ll_conn_hci_chk_conn_params(hcc_params->conn_itvl_min,
650                                              hcc_params->conn_itvl_max,
651                                              hcc_params->conn_latency,
652                                              hcc_params->supervision_timeout);
653         if (rc) {
654             return rc;
655         }
656         iter += 8;
657 
658         /* Min/max connection event lengths */
659         hcc_params->min_ce_len = get_le16(cmdbuf + iter);
660         hcc_params->max_ce_len = get_le16(cmdbuf + iter + 2);
661         if (hcc_params->min_ce_len > hcc_params->max_ce_len) {
662             return BLE_ERR_INV_HCI_CMD_PARMS;
663         }
664 
665         iter += 4;
666     }
667 #endif
668 
669 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
670     if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) {
671         /* validate length */
672         if (cmdlen < iter + 16) {
673             return BLE_ERR_INV_HCI_CMD_PARMS;
674         }
675 
676         hcc_params = &hcc->params[2];
677         hcc_params->scan_itvl = get_le16(cmdbuf + iter);
678         hcc_params->scan_window = get_le16(cmdbuf + iter + 2);
679         iter += 4;
680 
681         rc = ble_ll_conn_hci_chk_scan_params(hcc_params->scan_itvl,
682                                              hcc_params->scan_window);
683         if (rc) {
684             return rc;
685         }
686 
687         hcc_params->conn_itvl_min = get_le16(cmdbuf + iter);
688         hcc_params->conn_itvl_max = get_le16(cmdbuf + iter + 2);
689         hcc_params->conn_latency = get_le16(cmdbuf + iter + 4);
690         hcc_params->supervision_timeout = get_le16(cmdbuf + iter + 6);
691         rc = ble_ll_conn_hci_chk_conn_params(hcc_params->conn_itvl_min,
692                                              hcc_params->conn_itvl_max,
693                                              hcc_params->conn_latency,
694                                              hcc_params->supervision_timeout);
695         if (rc) {
696             return rc;
697         }
698         iter += 8;
699 
700         /* Min/max connection event lengths */
701         hcc_params->min_ce_len = get_le16(cmdbuf + iter);
702         hcc_params->max_ce_len = get_le16(cmdbuf + iter + 2);
703         if (hcc_params->min_ce_len > hcc_params->max_ce_len) {
704             return BLE_ERR_INV_HCI_CMD_PARMS;
705         }
706 
707         iter += 4;
708         if (valid_param_idx < 0) {
709             valid_param_idx = 2;
710         }
711     }
712 #endif
713 
714     /* Make sure we can allocate an event to send the connection complete */
715     if (ble_ll_init_alloc_conn_comp_ev()) {
716         return BLE_ERR_MEM_CAPACITY;
717     }
718 
719     /* Make sure we can accept a connection! */
720     connsm = ble_ll_conn_sm_get();
721     if (connsm == NULL) {
722         return BLE_ERR_CONN_LIMIT;
723     }
724 
725     ble_ll_conn_init_hcc_params(hcc, valid_param_idx);
726 
727     /* Initialize state machine in master role and start state machine */
728     ble_ll_conn_ext_master_init(connsm, hcc);
729     ble_ll_conn_sm_new(connsm);
730 
731     /* CSA will be selected when advertising is received */
732 
733     /* Start scanning */
734     rc = ble_ll_scan_ext_initiator_start(hcc, &connsm->scansm);
735     if (rc) {
736         SLIST_REMOVE(&g_ble_ll_conn_active_list,connsm,ble_ll_conn_sm,act_sle);
737         STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
738     } else {
739         /* Set the connection state machine we are trying to create. */
740         g_ble_ll_conn_create_sm = connsm;
741     }
742 
743     return rc;
744 }
745 #endif
746 
747 static int
ble_ll_conn_process_conn_params(uint8_t * cmdbuf,struct ble_ll_conn_sm * connsm)748 ble_ll_conn_process_conn_params(uint8_t *cmdbuf, struct ble_ll_conn_sm *connsm)
749 {
750     int rc;
751     struct hci_conn_update *hcu;
752 
753     /* Retrieve command data */
754     hcu = &connsm->conn_param_req;
755     hcu->handle = connsm->conn_handle;
756     hcu->conn_itvl_min = get_le16(cmdbuf + 2);
757     hcu->conn_itvl_max = get_le16(cmdbuf + 4);
758     hcu->conn_latency = get_le16(cmdbuf + 6);
759     hcu->supervision_timeout = get_le16(cmdbuf + 8);
760     hcu->min_ce_len = get_le16(cmdbuf + 10);
761     hcu->max_ce_len = get_le16(cmdbuf + 12);
762 
763     /* Check that parameter values are in range */
764     rc = ble_ll_conn_hci_chk_conn_params(hcu->conn_itvl_min,
765                                          hcu->conn_itvl_max,
766                                          hcu->conn_latency,
767                                          hcu->supervision_timeout);
768 
769     /* Check valid min/max ce length */
770     if (rc || (hcu->min_ce_len > hcu->max_ce_len)) {
771         hcu->handle = 0;
772         return BLE_ERR_INV_HCI_CMD_PARMS;
773     }
774     return rc;
775 }
776 
777 /**
778  * Called when the host issues the read remote features command
779  *
780  * @param cmdbuf
781  *
782  * @return int
783  */
784 int
ble_ll_conn_hci_read_rem_features(uint8_t * cmdbuf)785 ble_ll_conn_hci_read_rem_features(uint8_t *cmdbuf)
786 {
787     uint16_t handle;
788     struct ble_ll_conn_sm *connsm;
789 
790     /* If no connection handle exit with error */
791     handle = get_le16(cmdbuf);
792     connsm = ble_ll_conn_find_active_conn(handle);
793     if (!connsm) {
794         return BLE_ERR_UNK_CONN_ID;
795     }
796 
797     /* If already pending exit with error */
798     if (connsm->csmflags.cfbit.pending_hci_rd_features) {
799         return BLE_ERR_CMD_DISALLOWED;
800     }
801 
802     /*
803      * Start control procedure if we did not receive peer's features and did not
804      * start procedure already.
805      */
806     if (!connsm->csmflags.cfbit.rxd_features &&
807                 !IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG)) {
808         if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) &&
809             !(ble_ll_read_supp_features() & BLE_LL_FEAT_SLAVE_INIT)) {
810                 return BLE_ERR_CMD_DISALLOWED;
811         }
812 
813         ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG);
814     }
815 
816     connsm->csmflags.cfbit.pending_hci_rd_features = 1;
817 
818     return BLE_ERR_SUCCESS;
819 }
820 
821 /**
822  * Called to process a connection update command.
823  *
824  * @param cmdbuf
825  *
826  * @return int
827  */
828 int
ble_ll_conn_hci_update(uint8_t * cmdbuf)829 ble_ll_conn_hci_update(uint8_t *cmdbuf)
830 {
831     int rc;
832     uint8_t ctrl_proc;
833     uint16_t handle;
834     struct ble_ll_conn_sm *connsm;
835     struct hci_conn_update *hcu;
836 
837     /*
838      * XXX: must deal with slave not supporting this feature and using
839      * conn update! Right now, we only check if WE support the connection
840      * parameters request procedure. We dont check if the remote does.
841      * We should also be able to deal with sending the parameter request,
842      * getting an UNKOWN_RSP ctrl pdu and resorting to use normal
843      * connection update procedure.
844      */
845 
846     /* If no connection handle exit with error */
847     handle = get_le16(cmdbuf);
848     connsm = ble_ll_conn_find_active_conn(handle);
849     if (!connsm) {
850         return BLE_ERR_UNK_CONN_ID;
851     }
852 
853     /* Better not have this procedure ongoing! */
854     if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ) ||
855         IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_UPDATE)) {
856         return BLE_ERR_CMD_DISALLOWED;
857     }
858 
859     /* See if this feature is supported on both sides */
860     if ((connsm->conn_features & BLE_LL_FEAT_CONN_PARM_REQ) == 0) {
861         if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
862             return BLE_ERR_UNSUPP_REM_FEATURE;
863         }
864         ctrl_proc = BLE_LL_CTRL_PROC_CONN_UPDATE;
865     } else {
866         ctrl_proc = BLE_LL_CTRL_PROC_CONN_PARAM_REQ;
867     }
868 
869     /*
870      * If we are a slave and the master has initiated the procedure already
871      * we should deny the slave request for now. If we are a master and the
872      * slave has initiated the procedure, we need to send a reject to the
873      * slave.
874      */
875     if (connsm->csmflags.cfbit.awaiting_host_reply) {
876         if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
877             return BLE_ERR_LMP_COLLISION;
878         } else {
879             connsm->csmflags.cfbit.awaiting_host_reply = 0;
880 
881             /* XXX: If this fails no reject ind will be sent! */
882             ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode,
883                                         BLE_ERR_LMP_COLLISION);
884         }
885     }
886 
887     /*
888      * If we are a slave and the master has initiated the channel map
889      * update procedure we should deny the slave request for now.
890      */
891     if (connsm->csmflags.cfbit.chanmap_update_scheduled) {
892         if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
893             return BLE_ERR_DIFF_TRANS_COLL;
894         }
895     }
896 
897     /* Retrieve command data */
898     hcu = &connsm->conn_param_req;
899     hcu->handle = handle;
900     hcu->conn_itvl_min = get_le16(cmdbuf + 2);
901     hcu->conn_itvl_max = get_le16(cmdbuf + 4);
902     hcu->conn_latency = get_le16(cmdbuf + 6);
903     hcu->supervision_timeout = get_le16(cmdbuf + 8);
904     hcu->min_ce_len = get_le16(cmdbuf + 10);
905     hcu->max_ce_len = get_le16(cmdbuf + 12);
906     if (hcu->min_ce_len > hcu->max_ce_len) {
907         return BLE_ERR_INV_HCI_CMD_PARMS;
908     }
909 
910     /* Check that parameter values are in range */
911     rc = ble_ll_conn_hci_chk_conn_params(hcu->conn_itvl_min,
912                                          hcu->conn_itvl_max,
913                                          hcu->conn_latency,
914                                          hcu->supervision_timeout);
915     if (!rc) {
916         /* Start the control procedure */
917         ble_ll_ctrl_proc_start(connsm, ctrl_proc);
918     }
919 
920     return rc;
921 }
922 
923 int
ble_ll_conn_hci_param_reply(uint8_t * cmdbuf,int positive_reply,uint8_t * rspbuf,uint8_t * rsplen)924 ble_ll_conn_hci_param_reply(uint8_t *cmdbuf, int positive_reply,
925                             uint8_t *rspbuf, uint8_t *rsplen)
926 {
927     int rc;
928     uint8_t ble_err;
929     uint8_t *dptr;
930     uint8_t rsp_opcode;
931     uint8_t len;
932     uint16_t handle;
933     struct os_mbuf *om;
934     struct ble_ll_conn_sm *connsm;
935 
936     handle = get_le16(cmdbuf);
937 
938     /* See if we support this feature */
939     if ((ble_ll_read_supp_features() & BLE_LL_FEAT_CONN_PARM_REQ) == 0) {
940         rc = BLE_ERR_UNKNOWN_HCI_CMD;
941         goto done;
942     }
943 
944     /* If we dont have a handle we cant do anything */
945     connsm = ble_ll_conn_find_active_conn(handle);
946     if (!connsm) {
947         rc = BLE_ERR_UNK_CONN_ID;
948         goto done;
949     }
950 
951     /* Make sure connection parameters are valid if this is a positive reply */
952     rc = BLE_ERR_SUCCESS;
953     ble_err = cmdbuf[2];
954     if (positive_reply) {
955         rc = ble_ll_conn_process_conn_params(cmdbuf, connsm);
956         if (rc) {
957             ble_err = BLE_ERR_CONN_PARMS;
958         }
959     }
960 
961     /* The connection should be awaiting a reply. If not, just discard */
962     if (connsm->csmflags.cfbit.awaiting_host_reply) {
963         /* Get a control packet buffer */
964         if (positive_reply && (rc == BLE_ERR_SUCCESS)) {
965             om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PAYLOAD + 1,
966                                     sizeof(struct ble_mbuf_hdr));
967             if (om) {
968                 dptr = om->om_data;
969                 rsp_opcode = ble_ll_ctrl_conn_param_reply(connsm, dptr,
970                                                           &connsm->conn_cp);
971                 dptr[0] = rsp_opcode;
972                 len = g_ble_ll_ctrl_pkt_lengths[rsp_opcode] + 1;
973                 ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len);
974             }
975         } else {
976             /* XXX: check return code and deal */
977             ble_ll_ctrl_reject_ind_send(connsm, connsm->host_reply_opcode,
978                                         ble_err);
979         }
980         connsm->csmflags.cfbit.awaiting_host_reply = 0;
981 
982         /* XXX: if we cant get a buffer, what do we do? We need to remember
983          * reason if it was a negative reply. We also would need to have
984            some state to tell us this happened */
985     }
986 
987 done:
988     put_le16(rspbuf, handle);
989     *rsplen = sizeof(uint16_t);
990     return rc;
991 }
992 
993 /* this is called from same context after cmd complete is send so it is
994  * safe to use g_ble_ll_conn_comp_ev
995  */
996 static void
ble_ll_conn_hci_cancel_conn_complete_event(void)997 ble_ll_conn_hci_cancel_conn_complete_event(void)
998 {
999     BLE_LL_ASSERT(g_ble_ll_conn_comp_ev);
1000 
1001     ble_ll_conn_comp_event_send(NULL, BLE_ERR_UNK_CONN_ID,
1002                                 g_ble_ll_conn_comp_ev, NULL);
1003     g_ble_ll_conn_comp_ev = NULL;
1004 }
1005 
1006 /**
1007  * Called when HCI command to cancel a create connection command has been
1008  * received.
1009  *
1010  * Context: Link Layer (HCI command parser)
1011  *
1012  * @return int
1013  */
1014 int
ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb * post_cmd_cb)1015 ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
1016 {
1017     int rc;
1018     struct ble_ll_conn_sm *connsm;
1019 
1020     /*
1021      * If we receive this command and we have not got a connection
1022      * create command, we have to return disallowed. The spec does not say
1023      * what happens if the connection has already been established. We
1024      * return disallowed as well
1025      */
1026     connsm = g_ble_ll_conn_create_sm;
1027     if (connsm && (connsm->conn_state == BLE_LL_CONN_STATE_IDLE)) {
1028         /* stop scanning and end the connection event */
1029         g_ble_ll_conn_create_sm = NULL;
1030         ble_ll_scan_sm_stop(1);
1031         ble_ll_conn_end(connsm, BLE_ERR_UNK_CONN_ID);
1032 
1033         *post_cmd_cb = ble_ll_conn_hci_cancel_conn_complete_event;
1034 
1035         rc = BLE_ERR_SUCCESS;
1036     } else {
1037         /* If we are not attempting to create a connection*/
1038         rc = BLE_ERR_CMD_DISALLOWED;
1039     }
1040 
1041     return rc;
1042 }
1043 
1044 /**
1045  * Called to process a HCI disconnect command
1046  *
1047  * Context: Link Layer task (HCI command parser).
1048  *
1049  * @param cmdbuf
1050  *
1051  * @return int
1052  */
1053 int
ble_ll_conn_hci_disconnect_cmd(uint8_t * cmdbuf)1054 ble_ll_conn_hci_disconnect_cmd(uint8_t *cmdbuf)
1055 {
1056     int rc;
1057     uint8_t reason;
1058     uint16_t handle;
1059     struct ble_ll_conn_sm *connsm;
1060 
1061     /* Check for valid parameters */
1062     handle = get_le16(cmdbuf);
1063     reason = cmdbuf[2];
1064 
1065     rc = BLE_ERR_INV_HCI_CMD_PARMS;
1066     if (handle <= BLE_LL_CONN_MAX_CONN_HANDLE) {
1067         /* Make sure reason is valid */
1068         switch (reason) {
1069         case BLE_ERR_AUTH_FAIL:
1070         case BLE_ERR_REM_USER_CONN_TERM:
1071         case BLE_ERR_RD_CONN_TERM_RESRCS:
1072         case BLE_ERR_RD_CONN_TERM_PWROFF:
1073         case BLE_ERR_UNSUPP_REM_FEATURE:
1074         case BLE_ERR_UNIT_KEY_PAIRING:
1075         case BLE_ERR_CONN_PARMS:
1076             connsm = ble_ll_conn_find_active_conn(handle);
1077             if (connsm) {
1078                 /* Do not allow command if we are in process of disconnecting */
1079                 if (connsm->disconnect_reason) {
1080                     rc = BLE_ERR_CMD_DISALLOWED;
1081                 } else {
1082                     /* This control procedure better not be pending! */
1083                     BLE_LL_ASSERT(CONN_F_TERMINATE_STARTED(connsm) == 0);
1084 
1085                     /* Record the disconnect reason */
1086                     connsm->disconnect_reason = reason;
1087 
1088                     /* Start this control procedure */
1089                     ble_ll_ctrl_terminate_start(connsm);
1090 
1091                     rc = BLE_ERR_SUCCESS;
1092                 }
1093             } else {
1094                 rc = BLE_ERR_UNK_CONN_ID;
1095             }
1096             break;
1097         default:
1098             break;
1099         }
1100     }
1101 
1102     return rc;
1103 }
1104 
1105 /**
1106  * Called to process a HCI disconnect command
1107  *
1108  * Context: Link Layer task (HCI command parser).
1109  *
1110  * @param cmdbuf
1111  *
1112  * @return int
1113  */
1114 int
ble_ll_conn_hci_rd_rem_ver_cmd(uint8_t * cmdbuf)1115 ble_ll_conn_hci_rd_rem_ver_cmd(uint8_t *cmdbuf)
1116 {
1117     uint16_t handle;
1118     struct ble_ll_conn_sm *connsm;
1119 
1120     /* Check for valid parameters */
1121     handle = get_le16(cmdbuf);
1122     connsm = ble_ll_conn_find_active_conn(handle);
1123     if (!connsm) {
1124         return BLE_ERR_UNK_CONN_ID;
1125     }
1126 
1127     /* Return error if in progress */
1128     if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG)) {
1129         return BLE_ERR_CMD_DISALLOWED;
1130     }
1131 
1132     /*
1133      * Start this control procedure. If we have already done this control
1134      * procedure we set the pending bit so that the host gets an event because
1135      * it is obviously expecting one (or would not have sent the command).
1136      * NOTE: we cant just send the event here. That would cause the event to
1137      * be queued before the command status.
1138      */
1139     if (!connsm->csmflags.cfbit.version_ind_sent) {
1140         ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG);
1141     } else {
1142         connsm->pending_ctrl_procs |= (1 << BLE_LL_CTRL_PROC_VERSION_XCHG);
1143     }
1144 
1145     return BLE_ERR_SUCCESS;
1146 }
1147 
1148 /**
1149  * Called to read the RSSI for a given connection handle
1150  *
1151  * @param cmdbuf
1152  * @param rspbuf
1153  * @param rsplen
1154  *
1155  * @return int
1156  */
1157 int
ble_ll_conn_hci_rd_rssi(uint8_t * cmdbuf,uint8_t * rspbuf,uint8_t * rsplen)1158 ble_ll_conn_hci_rd_rssi(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
1159 {
1160     int rc;
1161     int8_t rssi;
1162     uint16_t handle;
1163     struct ble_ll_conn_sm *connsm;
1164 
1165     handle = get_le16(cmdbuf);
1166     connsm = ble_ll_conn_find_active_conn(handle);
1167     if (!connsm) {
1168         rssi = 127;
1169         rc = BLE_ERR_UNK_CONN_ID;
1170     } else {
1171         rssi = connsm->conn_rssi;
1172         rc = BLE_ERR_SUCCESS;
1173     }
1174 
1175     put_le16(rspbuf, handle);
1176     rspbuf[2] = (uint8_t)rssi;
1177     *rsplen = 3;
1178 
1179     /* Place the RSSI of the connection into the response buffer */
1180     return rc;
1181 }
1182 
1183 /**
1184  * Called to read the current channel map of a connection
1185  *
1186  * @param cmdbuf
1187  * @param rspbuf
1188  * @param rsplen
1189  *
1190  * @return int
1191  */
1192 int
ble_ll_conn_hci_rd_chan_map(uint8_t * cmdbuf,uint8_t * rspbuf,uint8_t * rsplen)1193 ble_ll_conn_hci_rd_chan_map(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
1194 {
1195     int rc;
1196     uint16_t handle;
1197     struct ble_ll_conn_sm *connsm;
1198 
1199     handle = get_le16(cmdbuf);
1200     connsm = ble_ll_conn_find_active_conn(handle);
1201     if (!connsm) {
1202         rc = BLE_ERR_UNK_CONN_ID;
1203     } else {
1204         if (connsm->csmflags.cfbit.chanmap_update_scheduled) {
1205             memcpy(rspbuf + 2, &connsm->req_chanmap[0], BLE_LL_CONN_CHMAP_LEN);
1206         } else {
1207             memcpy(rspbuf + 2, &connsm->chanmap[0], BLE_LL_CONN_CHMAP_LEN);
1208         }
1209         rc = BLE_ERR_SUCCESS;
1210     }
1211 
1212     put_le16(rspbuf, handle);
1213     *rsplen = sizeof(uint16_t) + BLE_LL_CONN_CHMAP_LEN;
1214     return rc;
1215 }
1216 
1217 /**
1218  * Called when the host issues the LE command "set host channel classification"
1219  *
1220  * @param cmdbuf
1221  *
1222  * @return int
1223  */
1224 int
ble_ll_conn_hci_set_chan_class(uint8_t * cmdbuf)1225 ble_ll_conn_hci_set_chan_class(uint8_t *cmdbuf)
1226 {
1227     int rc;
1228     uint8_t num_used_chans;
1229 
1230     /*
1231      * The HCI command states that the host is allowed to mask in just one
1232      * channel but the Link Layer needs minimum two channels to operate. So
1233      * I will not allow this command if there are less than 2 channels masked.
1234      */
1235     rc = BLE_ERR_SUCCESS;
1236     num_used_chans = ble_ll_conn_calc_used_chans(cmdbuf);
1237     if ((num_used_chans < 2) || ((cmdbuf[4] & 0xe0) != 0)) {
1238         rc = BLE_ERR_INV_HCI_CMD_PARMS;
1239     }
1240 
1241     /* Set the host channel mask */
1242     ble_ll_conn_set_global_chanmap(num_used_chans, cmdbuf);
1243     return rc;
1244 }
1245 
1246 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) == 1)
1247 int
ble_ll_conn_hci_set_data_len(uint8_t * cmdbuf,uint8_t * rspbuf,uint8_t * rsplen)1248 ble_ll_conn_hci_set_data_len(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
1249 {
1250     int rc;
1251     uint16_t handle;
1252     uint16_t txoctets;
1253     uint16_t txtime;
1254     struct ble_ll_conn_sm *connsm;
1255 
1256     /* Find connection */
1257     handle = get_le16(cmdbuf);
1258     connsm = ble_ll_conn_find_active_conn(handle);
1259     if (!connsm) {
1260         rc = BLE_ERR_UNK_CONN_ID;
1261         goto done;
1262     }
1263 
1264     txoctets = get_le16(cmdbuf + 2);
1265     txtime = get_le16(cmdbuf + 4);
1266 
1267     /* Make sure it is valid */
1268     if (!ble_ll_chk_txrx_octets(txoctets) ||
1269         !ble_ll_chk_txrx_time(txtime)) {
1270         rc = BLE_ERR_INV_HCI_CMD_PARMS;
1271         goto done;
1272     }
1273 
1274     rc = BLE_ERR_SUCCESS;
1275     if (connsm->max_tx_time != txtime ||
1276         connsm->max_tx_octets != txoctets) {
1277 
1278         connsm->max_tx_time = txtime;
1279         connsm->max_tx_octets = txoctets;
1280 
1281         ble_ll_ctrl_initiate_dle(connsm);
1282     }
1283 
1284 done:
1285     put_le16(rspbuf, handle);
1286     *rsplen = sizeof(uint16_t);
1287     return rc;
1288 }
1289 #endif
1290 
1291 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
1292 /**
1293  * LE start encrypt command
1294  *
1295  * @param cmdbuf
1296  *
1297  * @return int
1298  */
1299 int
ble_ll_conn_hci_le_start_encrypt(uint8_t * cmdbuf)1300 ble_ll_conn_hci_le_start_encrypt(uint8_t *cmdbuf)
1301 {
1302     int rc;
1303     uint16_t handle;
1304     struct ble_ll_conn_sm *connsm;
1305 
1306     handle = get_le16(cmdbuf);
1307     connsm = ble_ll_conn_find_active_conn(handle);
1308     if (!connsm) {
1309         rc = BLE_ERR_UNK_CONN_ID;
1310     } else if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
1311         rc = BLE_ERR_UNSPECIFIED;
1312     } else if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT) {
1313         /*
1314          * The specification does not say what to do here but the host should
1315          * not be telling us to start encryption while we are in the process
1316          * of honoring a previous start encrypt.
1317          */
1318         rc = BLE_ERR_CMD_DISALLOWED;
1319     } else {
1320         /* Start the control procedure */
1321         connsm->enc_data.host_rand_num = get_le64(cmdbuf + 2);
1322         connsm->enc_data.enc_div = get_le16(cmdbuf + 10);
1323         swap_buf(connsm->enc_data.enc_block.key, cmdbuf + 12, 16);
1324         ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_ENCRYPT);
1325         rc = BLE_ERR_SUCCESS;
1326     }
1327 
1328     return rc;
1329 }
1330 
1331 /**
1332  * Called to process the LE long term key reply.
1333  *
1334  * Context: Link Layer Task.
1335  *
1336  * @param cmdbuf
1337  * @param rspbuf
1338  * @param ocf
1339  *
1340  * @return int
1341  */
1342 int
ble_ll_conn_hci_le_ltk_reply(uint8_t * cmdbuf,uint8_t * rspbuf,uint8_t * rsplen)1343 ble_ll_conn_hci_le_ltk_reply(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
1344 {
1345     int rc;
1346     uint16_t handle;
1347     struct ble_ll_conn_sm *connsm;
1348 
1349     /* Find connection handle */
1350     handle = get_le16(cmdbuf);
1351     connsm = ble_ll_conn_find_active_conn(handle);
1352     if (!connsm) {
1353         rc = BLE_ERR_UNK_CONN_ID;
1354         goto ltk_key_cmd_complete;
1355     }
1356 
1357     /* Should never get this if we are a master! */
1358     if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
1359         rc = BLE_ERR_UNSPECIFIED;
1360         goto ltk_key_cmd_complete;
1361     }
1362 
1363     /* The connection should be awaiting a reply. If not, just discard */
1364     if (connsm->enc_data.enc_state != CONN_ENC_S_LTK_REQ_WAIT) {
1365         rc = BLE_ERR_CMD_DISALLOWED;
1366         goto ltk_key_cmd_complete;
1367     }
1368 
1369     swap_buf(connsm->enc_data.enc_block.key, cmdbuf + 2, 16);
1370     ble_ll_calc_session_key(connsm);
1371     ble_ll_ctrl_start_enc_send(connsm);
1372     rc = BLE_ERR_SUCCESS;
1373 
1374 ltk_key_cmd_complete:
1375     put_le16(rspbuf, handle);
1376     *rsplen = sizeof(uint16_t);
1377     return rc;
1378 }
1379 
1380 /**
1381  * Called to process the LE long term key negative reply.
1382  *
1383  * Context: Link Layer Task.
1384  *
1385  * @param cmdbuf
1386  * @param rspbuf
1387  * @param ocf
1388  *
1389  * @return int
1390  */
1391 int
ble_ll_conn_hci_le_ltk_neg_reply(uint8_t * cmdbuf,uint8_t * rspbuf,uint8_t * rsplen)1392 ble_ll_conn_hci_le_ltk_neg_reply(uint8_t *cmdbuf, uint8_t *rspbuf,
1393                                  uint8_t *rsplen)
1394 {
1395     int rc;
1396     uint16_t handle;
1397     struct ble_ll_conn_sm *connsm;
1398 
1399     /* Find connection handle */
1400     handle = get_le16(cmdbuf);
1401     connsm = ble_ll_conn_find_active_conn(handle);
1402     if (!connsm) {
1403         rc = BLE_ERR_UNK_CONN_ID;
1404         goto ltk_key_cmd_complete;
1405     }
1406 
1407     /* Should never get this if we are a master! */
1408     if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
1409         rc = BLE_ERR_UNSPECIFIED;
1410         goto ltk_key_cmd_complete;
1411     }
1412 
1413     /* The connection should be awaiting a reply. If not, just discard */
1414     if (connsm->enc_data.enc_state != CONN_ENC_S_LTK_REQ_WAIT) {
1415         rc = BLE_ERR_CMD_DISALLOWED;
1416         goto ltk_key_cmd_complete;
1417     }
1418 
1419     /* We received a negative reply! Send REJECT_IND */
1420     ble_ll_ctrl_reject_ind_send(connsm, BLE_LL_CTRL_ENC_REQ,
1421                                 BLE_ERR_PINKEY_MISSING);
1422     connsm->enc_data.enc_state = CONN_ENC_S_LTK_NEG_REPLY;
1423 
1424     rc = BLE_ERR_SUCCESS;
1425 
1426 ltk_key_cmd_complete:
1427     put_le16(rspbuf, handle);
1428     *rsplen = sizeof(uint16_t);
1429     return rc;
1430 }
1431 #endif
1432 
1433 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) == 1)
1434 /**
1435  * Read authenticated payload timeout (OGF=3, OCF==0x007B)
1436  *
1437  * @param cmdbuf
1438  * @param rsplen
1439  *
1440  * @return int
1441  */
1442 int
ble_ll_conn_hci_rd_auth_pyld_tmo(uint8_t * cmdbuf,uint8_t * rsp,uint8_t * rsplen)1443 ble_ll_conn_hci_rd_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen)
1444 {
1445     int rc;
1446     uint16_t handle;
1447     struct ble_ll_conn_sm *connsm;
1448 
1449     handle = get_le16(cmdbuf);
1450     connsm = ble_ll_conn_find_active_conn(handle);
1451     if (!connsm) {
1452         rc = BLE_ERR_UNK_CONN_ID;
1453     } else {
1454         put_le16(rsp + 2, connsm->auth_pyld_tmo);
1455         rc = BLE_ERR_SUCCESS;
1456     }
1457 
1458     put_le16(rsp, handle);
1459     *rsplen = BLE_HCI_RD_AUTH_PYLD_TMO_LEN;
1460     return rc;
1461 }
1462 
1463 /**
1464  * Write authenticated payload timeout (OGF=3, OCF=00x7C)
1465  *
1466  * @param cmdbuf
1467  * @param rsplen
1468  *
1469  * @return int
1470  */
1471 int
ble_ll_conn_hci_wr_auth_pyld_tmo(uint8_t * cmdbuf,uint8_t * rsp,uint8_t * rsplen)1472 ble_ll_conn_hci_wr_auth_pyld_tmo(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen)
1473 {
1474     int rc;
1475     uint16_t handle;
1476     uint16_t tmo;
1477     uint32_t min_tmo;
1478     struct ble_ll_conn_sm *connsm;
1479 
1480     rc = BLE_ERR_SUCCESS;
1481 
1482     handle = get_le16(cmdbuf);
1483     connsm = ble_ll_conn_find_active_conn(handle);
1484     if (!connsm) {
1485         rc = BLE_ERR_UNK_CONN_ID;
1486         goto wr_auth_exit;
1487     }
1488 
1489     /*
1490      * The timeout is in units of 10 msecs. We need to make sure that the
1491      * timeout is greater than or equal to connItvl * (1 + slaveLatency)
1492      */
1493     tmo = get_le16(cmdbuf + 2);
1494     min_tmo = (uint32_t)connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
1495     min_tmo *= (connsm->slave_latency + 1);
1496     min_tmo /= 10000;
1497 
1498     if (tmo < min_tmo) {
1499         rc = BLE_ERR_INV_HCI_CMD_PARMS;
1500     } else {
1501         connsm->auth_pyld_tmo = tmo;
1502         if (ble_npl_callout_is_active(&connsm->auth_pyld_timer)) {
1503             ble_ll_conn_auth_pyld_timer_start(connsm);
1504         }
1505     }
1506 
1507 wr_auth_exit:
1508     put_le16(rsp, handle);
1509     *rsplen = BLE_HCI_WR_AUTH_PYLD_TMO_LEN;
1510     return rc;
1511 }
1512 #endif
1513 
1514 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
1515 /**
1516  * Read current phy for connection (OGF=8, OCF==0x0030)
1517  *
1518  * @param cmdbuf
1519  * @param rsplen
1520  *
1521  * @return int
1522  */
1523 int
ble_ll_conn_hci_le_rd_phy(uint8_t * cmdbuf,uint8_t * rsp,uint8_t * rsplen)1524 ble_ll_conn_hci_le_rd_phy(uint8_t *cmdbuf, uint8_t *rsp, uint8_t *rsplen)
1525 {
1526     int rc;
1527     uint16_t handle;
1528     struct ble_ll_conn_sm *connsm;
1529 
1530     handle = get_le16(cmdbuf);
1531     connsm = ble_ll_conn_find_active_conn(handle);
1532     if (!connsm) {
1533         rc = BLE_ERR_UNK_CONN_ID;
1534     } else {
1535         rsp[2] = connsm->phy_data.cur_tx_phy;
1536         rsp[3] = connsm->phy_data.cur_rx_phy;
1537         rc = BLE_ERR_SUCCESS;
1538     }
1539 
1540     put_le16(rsp, handle);
1541     *rsplen = BLE_HCI_LE_RD_PHY_RSPLEN;
1542     return rc;
1543 }
1544 
1545 /**
1546  * Set PHY preferences for connection
1547  *
1548  * @param cmdbuf
1549  *
1550  * @return int
1551  */
1552 int
ble_ll_conn_hci_le_set_phy(uint8_t * cmdbuf)1553 ble_ll_conn_hci_le_set_phy(uint8_t *cmdbuf)
1554 {
1555     int rc;
1556     uint16_t phy_options;
1557     uint8_t tx_phys;
1558     uint8_t rx_phys;
1559     uint16_t handle;
1560     struct ble_ll_conn_sm *connsm;
1561 
1562     handle = get_le16(cmdbuf);
1563     connsm = ble_ll_conn_find_active_conn(handle);
1564     if (!connsm) {
1565         return BLE_ERR_UNK_CONN_ID;
1566     }
1567 
1568     /*
1569      * If host has requested a PHY update and we are not finished do
1570      * not allow another one
1571      */
1572     if (CONN_F_HOST_PHY_UPDATE(connsm)) {
1573         return BLE_ERR_CMD_DISALLOWED;
1574     }
1575 
1576     phy_options = get_le16(cmdbuf + 5);
1577     if (phy_options > BLE_HCI_LE_PHY_CODED_S8_PREF) {
1578         return BLE_ERR_INV_HCI_CMD_PARMS;
1579     }
1580 
1581     /* Check valid parameters */
1582     rc = ble_ll_hci_chk_phy_masks(cmdbuf + 2, &tx_phys, &rx_phys);
1583     if (rc) {
1584         goto phy_cmd_param_err;
1585     }
1586 
1587     connsm->phy_data.phy_options = phy_options & 0x03;
1588     connsm->phy_data.host_pref_tx_phys_mask = tx_phys,
1589     connsm->phy_data.host_pref_rx_phys_mask = rx_phys;
1590 
1591     /*
1592      * The host preferences override the default phy preferences. Currently,
1593      * the only reason the controller will initiate a procedure on its own
1594      * is due to the fact that the host set default preferences. So if there
1595      * is a pending control procedure and it has not yet started, we do not
1596      * need to perform the default controller procedure.
1597      */
1598     if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE)) {
1599         if (connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_PHY_UPDATE) {
1600             CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
1601         }
1602         CONN_F_HOST_PHY_UPDATE(connsm) = 1;
1603     } else {
1604         /*
1605          * We could be doing a peer-initiated PHY update procedure. If this
1606          * is the case the requested phy preferences will not both be 0. If
1607          * we are not done with a peer-initiated procedure we just set the
1608          * pending bit but do not start the control procedure.
1609          */
1610         if (CONN_F_PEER_PHY_UPDATE(connsm)) {
1611             connsm->pending_ctrl_procs |= BLE_LL_CTRL_PROC_PHY_UPDATE;
1612             CONN_F_HOST_PHY_UPDATE(connsm) = 1;
1613         } else {
1614             /* Check if we should start phy update procedure */
1615             if (!ble_ll_conn_chk_phy_upd_start(connsm)) {
1616                 CONN_F_HOST_PHY_UPDATE(connsm) = 1;
1617             } else {
1618                 /*
1619                  * Set flag to send a PHY update complete event. We set flag
1620                  * even if we do not do an update procedure since we have to
1621                  * inform the host even if we decide not to change anything.
1622                  */
1623                 CONN_F_PHY_UPDATE_EVENT(connsm) = 1;
1624             }
1625         }
1626     }
1627 
1628 phy_cmd_param_err:
1629     return rc;
1630 }
1631 #endif
1632