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