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 #include <stdint.h>
20 #include <assert.h>
21 #include <string.h>
22 #include "syscfg/syscfg.h"
23 #include "nimble/ble.h"
24 #include "nimble/nimble_opt.h"
25 #include "nimble/hci_common.h"
26 #include "controller/ble_ll.h"
27 #include "controller/ble_ll_hci.h"
28 #include "controller/ble_ll_ctrl.h"
29 #include "controller/ble_ll_trace.h"
30 #include "controller/ble_hw.h"
31 #include "ble_ll_conn_priv.h"
32
33 /* To use spec sample data for testing */
34 #undef BLE_LL_ENCRYPT_USE_TEST_DATA
35
36 /*
37 * For console debug to show session key calculation. NOTE: if you define
38 * this the stack requirements for the LL task go up considerably. The
39 * default stack will not be enough and must be increased.
40 */
41 #undef BLE_LL_ENCRYPT_DEBUG
42 #ifdef BLE_LL_ENCRYPT_DEBUG
43 #include "console/console.h"
44 #endif
45
46 /*
47 * XXX:
48 * 1) Do I need to keep track of which procedures have already been done?
49 * Do I need to worry about repeating procedures?
50 * 2) Should we create pool of control pdu's?. Dont need more
51 * than the # of connections and can probably deal with quite a few less
52 * if we have lots of connections.
53 * 3) What about procedures that have been completed but try to restart?
54 * 4) NOTE: there is a supported features procedure. However, in the case
55 * of data length extension, if the receiving device does not understand
56 * the pdu or it does not support data length extension, the LL_UNKNOWN_RSP
57 * pdu is sent. That needs to be processed...
58 * 5) We are supposed to remember when we do the data length update proc if
59 * the device sent us an unknown rsp. We should not send it another len req.
60 * Implement this how? Through remote supported features?
61 * 8) How to count control pdus sent. DO we count enqueued + sent, or only
62 * sent (actually attempted to tx). Do we count failures? How?
63 */
64
65 /*
66 * XXX: I definitely have an issue with control procedures and connection
67 * param request procedure and connection update procedure. This was
68 * noted when receiving an unknown response. Right now, I am getting confused
69 * with connection parameter request and updates regarding which procedures
70 * are running. So I need to go look through all the code and see where I
71 * used the request procedure and the update procedure and make sure I am doing
72 * the correct thing.
73 */
74
75 /*
76 * This array contains the length of the CtrData field in LL control PDU's.
77 * Note that there is a one byte opcode which precedes this field in the LL
78 * control PDU, so total data channel payload length for the control pdu is
79 * one greater.
80 */
81 const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES] =
82 {
83 BLE_LL_CTRL_CONN_UPD_REQ_LEN,
84 BLE_LL_CTRL_CHAN_MAP_LEN,
85 BLE_LL_CTRL_TERMINATE_IND_LEN,
86 BLE_LL_CTRL_ENC_REQ_LEN,
87 BLE_LL_CTRL_ENC_RSP_LEN,
88 BLE_LL_CTRL_START_ENC_REQ_LEN,
89 BLE_LL_CTRL_START_ENC_RSP_LEN,
90 BLE_LL_CTRL_UNK_RSP_LEN,
91 BLE_LL_CTRL_FEATURE_LEN,
92 BLE_LL_CTRL_FEATURE_LEN,
93 BLE_LL_CTRL_PAUSE_ENC_REQ_LEN,
94 BLE_LL_CTRL_PAUSE_ENC_RSP_LEN,
95 BLE_LL_CTRL_VERSION_IND_LEN,
96 BLE_LL_CTRL_REJ_IND_LEN,
97 BLE_LL_CTRL_SLAVE_FEATURE_REQ_LEN,
98 BLE_LL_CTRL_CONN_PARAMS_LEN,
99 BLE_LL_CTRL_CONN_PARAMS_LEN,
100 BLE_LL_CTRL_REJECT_IND_EXT_LEN,
101 BLE_LL_CTRL_PING_LEN,
102 BLE_LL_CTRL_PING_LEN,
103 BLE_LL_CTRL_LENGTH_REQ_LEN,
104 BLE_LL_CTRL_LENGTH_REQ_LEN,
105 BLE_LL_CTRL_PHY_REQ_LEN,
106 BLE_LL_CTRL_PHY_RSP_LEN,
107 BLE_LL_CTRL_PHY_UPD_IND_LEN,
108 BLE_LL_CTRL_MIN_USED_CHAN_LEN
109 };
110
111 /**
112 * Called to determine if a LL control procedure with an instant has
113 * been initiated.
114 *
115 * If the function returns a 0 it means no conflicting procedure has
116 * been initiated. Otherwise it returns the appropriate BLE error code to
117 * send.
118 *
119 * @param connsm Pointer to connection state machine.
120 * @param req_ctrl_proc The procedure that the peer is trying to initiate
121 *
122 * @return uint8_t
123 */
124 uint8_t
ble_ll_ctrl_proc_with_instant_initiated(struct ble_ll_conn_sm * connsm,uint8_t req_ctrl_proc)125 ble_ll_ctrl_proc_with_instant_initiated(struct ble_ll_conn_sm *connsm,
126 uint8_t req_ctrl_proc)
127 {
128 uint8_t err;
129
130 switch (connsm->cur_ctrl_proc) {
131 case BLE_LL_CTRL_PROC_PHY_UPDATE:
132 case BLE_LL_CTRL_PROC_CONN_UPDATE:
133 case BLE_LL_CTRL_PROC_CONN_PARAM_REQ:
134 case BLE_LL_CTRL_PROC_CHAN_MAP_UPD:
135 if (req_ctrl_proc == connsm->cur_ctrl_proc) {
136 err = BLE_ERR_LMP_COLLISION;
137 } else if ((connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_CONN_UPDATE) &&
138 (req_ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) {
139 err = BLE_ERR_LMP_COLLISION;
140 } else {
141 err = BLE_ERR_DIFF_TRANS_COLL;
142 }
143 break;
144 default:
145 err = 0;
146 }
147
148 return err;
149 }
150
151 /**
152 * Create a LL_REJECT_EXT_IND pdu.
153 *
154 * @param rej_opcode Opcode to be rejected.
155 * @param err: error response
156 * @param ctrdata: Pointer to where CtrData starts in pdu
157 */
158 void
ble_ll_ctrl_rej_ext_ind_make(uint8_t rej_opcode,uint8_t err,uint8_t * ctrdata)159 ble_ll_ctrl_rej_ext_ind_make(uint8_t rej_opcode, uint8_t err, uint8_t *ctrdata)
160 {
161 ctrdata[0] = rej_opcode;
162 ctrdata[1] = err;
163 }
164
165 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
166 /**
167 * Called to cancel a phy update procedure.
168 *
169 * @param connsm
170 * @param ble_err
171 */
172 void
ble_ll_ctrl_phy_update_cancel(struct ble_ll_conn_sm * connsm,uint8_t ble_err)173 ble_ll_ctrl_phy_update_cancel(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
174 {
175 /* cancel any pending phy update procedures */
176 CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
177
178 /* Check if the host wants an event */
179 if (CONN_F_HOST_PHY_UPDATE(connsm)) {
180 ble_ll_hci_ev_phy_update(connsm, ble_err);
181 CONN_F_HOST_PHY_UPDATE(connsm) = 0;
182 }
183
184 /* Clear any bits for phy updates that might be in progress */
185 CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
186 }
187 #endif
188
189 static int
ble_ll_ctrl_len_proc(struct ble_ll_conn_sm * connsm,uint8_t * dptr)190 ble_ll_ctrl_len_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
191 {
192 int rc;
193 struct ble_ll_len_req ctrl_req;
194
195 /* Extract parameters and check if valid */
196 ctrl_req.max_rx_bytes = get_le16(dptr);
197 ctrl_req.max_rx_time = get_le16(dptr + 2);
198 ctrl_req.max_tx_bytes = get_le16(dptr + 4);
199 ctrl_req.max_tx_time = get_le16(dptr + 6);
200
201 if ((ctrl_req.max_rx_bytes < BLE_LL_CONN_SUPP_BYTES_MIN) ||
202 (ctrl_req.max_rx_time < BLE_LL_CONN_SUPP_TIME_MIN) ||
203 (ctrl_req.max_tx_bytes < BLE_LL_CONN_SUPP_BYTES_MIN) ||
204 (ctrl_req.max_tx_time < BLE_LL_CONN_SUPP_TIME_MIN)) {
205 rc = 1;
206 } else {
207 /* Update the connection with the new parameters */
208 ble_ll_conn_datalen_update(connsm, &ctrl_req);
209 rc = 0;
210 }
211
212 return rc;
213 }
214
215 /**
216 * Process a received LL_PING_RSP control pdu.
217 *
218 * NOTE: we dont have to reset the callout since this packet will have had a
219 * valid MIC and that will restart the authenticated payload timer
220 *
221 * @param connsm
222 */
223 static void
ble_ll_ctrl_rx_ping_rsp(struct ble_ll_conn_sm * connsm)224 ble_ll_ctrl_rx_ping_rsp(struct ble_ll_conn_sm *connsm)
225 {
226 /* Stop the control procedure */
227 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_LE_PING);
228 }
229
230 /**
231 * Called when we receive either a connection parameter request or response.
232 *
233 * @param connsm
234 * @param dptr
235 * @param rspbuf
236 * @param opcode
237 *
238 * @return int
239 */
240 static int
ble_ll_ctrl_conn_param_pdu_proc(struct ble_ll_conn_sm * connsm,uint8_t * dptr,uint8_t * rspbuf,uint8_t opcode)241 ble_ll_ctrl_conn_param_pdu_proc(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
242 uint8_t *rspbuf, uint8_t opcode)
243 {
244 int rc;
245 int indicate;
246 uint8_t rsp_opcode;
247 uint8_t ble_err;
248 struct ble_ll_conn_params *req;
249 struct hci_conn_update *hcu;
250
251 /* Extract parameters and check if valid */
252 req = &connsm->conn_cp;
253 req->interval_min = get_le16(dptr);
254 req->interval_max = get_le16(dptr + 2);
255 req->latency = get_le16(dptr + 4);
256 req->timeout = get_le16(dptr + 6);
257 req->pref_periodicity = dptr[8];
258 req->ref_conn_event_cnt = get_le16(dptr + 9);
259 req->offset0 = get_le16(dptr + 11);
260 req->offset1 = get_le16(dptr + 13);
261 req->offset2 = get_le16(dptr + 15);
262 req->offset3 = get_le16(dptr + 17);
263 req->offset4 = get_le16(dptr + 19);
264 req->offset5 = get_le16(dptr + 21);
265
266 /* Check if parameters are valid */
267 ble_err = BLE_ERR_SUCCESS;
268 rc = ble_ll_conn_hci_chk_conn_params(req->interval_min,
269 req->interval_max,
270 req->latency,
271 req->timeout);
272 if (rc) {
273 ble_err = BLE_ERR_INV_LMP_LL_PARM;
274 goto conn_param_pdu_exit;
275 }
276
277 /*
278 * Check if there is a requested change to either the interval, timeout
279 * or latency. If not, this may just be an anchor point change and we do
280 * not have to notify the host.
281 * XXX: what if we dont like the parameters? When do we check that out?
282 */
283 indicate = 1;
284 if (opcode == BLE_LL_CTRL_CONN_PARM_REQ) {
285 if ((connsm->conn_itvl >= req->interval_min) &&
286 (connsm->conn_itvl <= req->interval_max) &&
287 (connsm->supervision_tmo == req->timeout) &&
288 (connsm->slave_latency == req->latency)) {
289 indicate = 0;
290 goto conn_parm_req_do_indicate;
291 }
292 }
293
294 /*
295 * A change has been requested. Is it within the values specified by
296 * the host? Note that for a master we will not be processing a
297 * connect param request from a slave if we are currently trying to
298 * update the connection parameters. This means that the previous
299 * check is all we need for a master (when receiving a request).
300 */
301 if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) ||
302 (opcode == BLE_LL_CTRL_CONN_PARM_RSP)) {
303 /*
304 * Not sure what to do about the slave. It is possible that the
305 * current connection parameters are not the same ones as the local host
306 * has provided? Not sure what to do here. Do we need to remember what
307 * host sent us? For now, I will assume that we need to remember what
308 * the host sent us and check it out.
309 */
310 hcu = &connsm->conn_param_req;
311 if (hcu->handle != 0) {
312 if (!((req->interval_min < hcu->conn_itvl_min) ||
313 (req->interval_min > hcu->conn_itvl_max) ||
314 (req->interval_max < hcu->conn_itvl_min) ||
315 (req->interval_max > hcu->conn_itvl_max) ||
316 (req->latency != hcu->conn_latency) ||
317 (req->timeout != hcu->supervision_timeout))) {
318 indicate = 0;
319 }
320 }
321 }
322
323 conn_parm_req_do_indicate:
324 /*
325 * XXX: are the connection update parameters acceptable? If not, we will
326 * need to know before we indicate to the host that they are acceptable.
327 */
328 if (indicate) {
329 /* If Host masked out Remote Connection Parameter Request Event, we need to
330 * send Reject back to the remote device
331 */
332 if (!ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ)){
333 ble_err = BLE_ERR_UNSUPP_REM_FEATURE;
334 goto conn_param_pdu_exit;
335 }
336
337 /*
338 * Send event to host. At this point we leave and wait to get
339 * an answer.
340 */
341 ble_ll_hci_ev_rem_conn_parm_req(connsm, req);
342 connsm->host_reply_opcode = opcode;
343 connsm->csmflags.cfbit.awaiting_host_reply = 1;
344 rsp_opcode = 255;
345 } else {
346 /* Create reply to connection request */
347 rsp_opcode = ble_ll_ctrl_conn_param_reply(connsm, rspbuf, req);
348 }
349
350 conn_param_pdu_exit:
351 if (ble_err) {
352 rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT;
353 rspbuf[1] = opcode;
354 rspbuf[2] = ble_err;
355 }
356 return rsp_opcode;
357 }
358
359 /**
360 * Called to make a connection update request LL control PDU
361 *
362 * Context: Link Layer
363 *
364 * @param connsm
365 * @param rsp
366 */
367 static void
ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm * connsm,uint8_t * pyld,struct ble_ll_conn_params * cp)368 ble_ll_ctrl_conn_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld,
369 struct ble_ll_conn_params *cp)
370 {
371 uint16_t instant;
372 uint32_t dt;
373 uint32_t num_old_ce;
374 uint32_t new_itvl_usecs;
375 uint32_t old_itvl_usecs;
376 struct hci_conn_update *hcu;
377 struct ble_ll_conn_upd_req *req;
378
379 /*
380 * Set instant. We set the instant to the current event counter plus
381 * the amount of slave latency as the slave may not be listening
382 * at every connection interval and we are not sure when the connect
383 * request will actually get sent. We add one more event plus the
384 * minimum as per the spec of 6 connection events.
385 */
386 instant = connsm->event_cntr + connsm->slave_latency + 6 + 1;
387
388 /*
389 * XXX: This should change in the future, but for now we will just
390 * start the new instant at the same anchor using win offset 0.
391 */
392 /* Copy parameters in connection update structure */
393 hcu = &connsm->conn_param_req;
394 req = &connsm->conn_update_req;
395 if (cp) {
396 /* XXX: so we need to make the new anchor point some time away
397 * from txwinoffset by some amount of msecs. Not sure how to do
398 that here. We dont need to, but we should. */
399 /* Calculate offset from requested offsets (if any) */
400 if (cp->offset0 != 0xFFFF) {
401 new_itvl_usecs = cp->interval_max * BLE_LL_CONN_ITVL_USECS;
402 old_itvl_usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
403 if ((int16_t)(cp->ref_conn_event_cnt - instant) >= 0) {
404 num_old_ce = cp->ref_conn_event_cnt - instant;
405 dt = old_itvl_usecs * num_old_ce;
406 dt += (cp->offset0 * BLE_LL_CONN_ITVL_USECS);
407 dt = dt % new_itvl_usecs;
408 } else {
409 num_old_ce = instant - cp->ref_conn_event_cnt;
410 dt = old_itvl_usecs * num_old_ce;
411 dt -= (cp->offset0 * BLE_LL_CONN_ITVL_USECS);
412 dt = dt % new_itvl_usecs;
413 dt = new_itvl_usecs - dt;
414 }
415 req->winoffset = dt / BLE_LL_CONN_TX_WIN_USECS;
416 } else {
417 req->winoffset = 0;
418 }
419 req->interval = cp->interval_max;
420 req->timeout = cp->timeout;
421 req->latency = cp->latency;
422 req->winsize = 1;
423 } else {
424 req->interval = hcu->conn_itvl_max;
425 req->timeout = hcu->supervision_timeout;
426 req->latency = hcu->conn_latency;
427 req->winoffset = 0;
428 req->winsize = connsm->tx_win_size;
429 }
430 req->instant = instant;
431
432 /* XXX: make sure this works for the connection parameter request proc. */
433 pyld[0] = req->winsize;
434 put_le16(pyld + 1, req->winoffset);
435 put_le16(pyld + 3, req->interval);
436 put_le16(pyld + 5, req->latency);
437 put_le16(pyld + 7, req->timeout);
438 put_le16(pyld + 9, instant);
439
440 /* Set flag in state machine to denote we have scheduled an update */
441 connsm->csmflags.cfbit.conn_update_sched = 1;
442 }
443
444 /**
445 * Called to process and UNKNOWN_RSP LL control packet.
446 *
447 * Context: Link Layer Task
448 *
449 * @param dptr
450 */
451 static int
ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm * connsm,uint8_t * dptr,uint8_t * rspdata)452 ble_ll_ctrl_proc_unk_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr, uint8_t *rspdata)
453 {
454 uint8_t ctrl_proc;
455 uint8_t opcode;
456
457 /* Get opcode of unknown LL control frame */
458 opcode = dptr[0];
459
460 /* Convert opcode to control procedure id */
461 switch (opcode) {
462 case BLE_LL_CTRL_LENGTH_REQ:
463 ctrl_proc = BLE_LL_CTRL_PROC_DATA_LEN_UPD;
464 BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_DATA_LEN_EXT);
465 break;
466 case BLE_LL_CTRL_CONN_UPDATE_IND:
467 ctrl_proc = BLE_LL_CTRL_PROC_CONN_UPDATE;
468 break;
469 case BLE_LL_CTRL_SLAVE_FEATURE_REQ:
470 ctrl_proc = BLE_LL_CTRL_PROC_FEATURE_XCHG;
471 BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_SLAVE_INIT);
472 break;
473 case BLE_LL_CTRL_CONN_PARM_REQ:
474 BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_CONN_PARM_REQ);
475 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
476 ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL);
477 connsm->reject_reason = BLE_ERR_SUCCESS;
478 return BLE_LL_CTRL_CONN_UPDATE_IND;
479 }
480 /* note: fall-through intentional */
481 case BLE_LL_CTRL_CONN_PARM_RSP:
482 ctrl_proc = BLE_LL_CTRL_PROC_CONN_PARAM_REQ;
483 break;
484 case BLE_LL_CTRL_PING_REQ:
485 /* LL can authenticate remote device even if remote device does not
486 * support LE Ping feature.
487 */
488 ctrl_proc = BLE_LL_CTRL_PROC_LE_PING;
489 BLE_LL_CONN_CLEAR_FEATURE(connsm, BLE_LL_FEAT_LE_PING);
490 break;
491 #if (BLE_LL_BT5_PHY_SUPPORTED ==1)
492 case BLE_LL_CTRL_PHY_REQ:
493 ble_ll_ctrl_phy_update_cancel(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
494 ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE;
495 break;
496 #endif
497 default:
498 ctrl_proc = BLE_LL_CTRL_PROC_NUM;
499 break;
500 }
501
502 /* If we are running this one currently, stop it */
503 if (connsm->cur_ctrl_proc == ctrl_proc) {
504 /* Stop the control procedure */
505 ble_ll_ctrl_proc_stop(connsm, ctrl_proc);
506 if (ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ) {
507 ble_ll_hci_ev_conn_update(connsm, BLE_ERR_UNSUPP_REM_FEATURE);
508 } else if (ctrl_proc == BLE_LL_CTRL_PROC_FEATURE_XCHG) {
509 if (connsm->csmflags.cfbit.pending_hci_rd_features) {
510 ble_ll_hci_ev_rd_rem_used_feat(connsm,
511 BLE_ERR_UNSUPP_REM_FEATURE);
512 }
513 connsm->csmflags.cfbit.pending_hci_rd_features = 0;
514 }
515 }
516
517 return BLE_ERR_MAX;
518 }
519
520 /**
521 * Callback when LL control procedure times out (for a given connection). If
522 * this is called, it means that we need to end the connection because it
523 * has not responded to a LL control request.
524 *
525 * Context: Link Layer
526 *
527 * @param arg Pointer to connection state machine.
528 */
529 static void
ble_ll_ctrl_proc_rsp_timer_cb(struct ble_npl_event * ev)530 ble_ll_ctrl_proc_rsp_timer_cb(struct ble_npl_event *ev)
531 {
532 /* Control procedure has timed out. Kill the connection */
533 ble_ll_conn_timeout((struct ble_ll_conn_sm *)ble_npl_event_get_arg(ev),
534 BLE_ERR_LMP_LL_RSP_TMO);
535 }
536
537 static void
ble_ll_ctrl_start_rsp_timer(struct ble_ll_conn_sm * connsm)538 ble_ll_ctrl_start_rsp_timer(struct ble_ll_conn_sm *connsm)
539 {
540 ble_npl_callout_init(&connsm->ctrl_proc_rsp_timer,
541 &g_ble_ll_data.ll_evq,
542 ble_ll_ctrl_proc_rsp_timer_cb,
543 connsm);
544
545 /* Re-start timer. Control procedure timeout is 40 seconds */
546 ble_npl_callout_reset(&connsm->ctrl_proc_rsp_timer,
547 ble_npl_time_ms_to_ticks32(BLE_LL_CTRL_PROC_TIMEOUT_MS));
548 }
549
550 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
551 void
ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm * connsm)552 ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm)
553 {
554 int chk_proc_stop;
555 int chk_host_phy;
556
557 chk_proc_stop = 1;
558 chk_host_phy = 1;
559
560 connsm->phy_tx_transition = BLE_PHY_TRANSITION_INVALID;
561
562 if (CONN_F_PEER_PHY_UPDATE(connsm)) {
563 CONN_F_PEER_PHY_UPDATE(connsm) = 0;
564 } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) {
565 CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
566 } else {
567 /* Must be a host-initiated update */
568 CONN_F_HOST_PHY_UPDATE(connsm) = 0;
569 chk_host_phy = 0;
570 if (CONN_F_PHY_UPDATE_EVENT(connsm) == 0) {
571 ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS);
572 }
573 }
574
575 /* Must check if we need to start host procedure */
576 if (chk_host_phy) {
577 if (CONN_F_HOST_PHY_UPDATE(connsm)) {
578 if (ble_ll_conn_chk_phy_upd_start(connsm)) {
579 CONN_F_HOST_PHY_UPDATE(connsm) = 0;
580 } else {
581 chk_proc_stop = 0;
582 }
583 }
584 }
585
586 if (chk_proc_stop) {
587 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
588 }
589 }
590
591 /**
592 * Convert a phy mask to a numeric phy value.
593 *
594 * NOTE: only one bit should be set here and there should be at least one.
595 * If this function returns a 0 it is an error!
596 *
597 * @param phy_mask Bitmask of phy
598 *
599 * @return uint8_t The numeric value associated with the phy mask
600 *
601 * BLE_HCI_LE_PHY_1M (1)
602 * BLE_HCI_LE_PHY_2M (2)
603 * BLE_HCI_LE_PHY_CODED (3)
604 */
605 static uint8_t
ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask)606 ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask)
607 {
608 uint8_t phy;
609
610 /*
611 * NOTE: wipe out unsupported PHYs. There should not be an unsupported
612 * in this mask if the other side is working correctly.
613 */
614 #if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
615 phy_mask &= ~BLE_HCI_LE_PHY_2M_PREF_MASK;
616 #endif
617 #if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
618 phy_mask &= ~BLE_HCI_LE_PHY_CODED_PREF_MASK;
619 #endif
620
621 if (phy_mask & BLE_PHY_MASK_1M) {
622 phy = BLE_PHY_1M;
623 phy_mask &= ~BLE_PHY_MASK_1M;
624 } else if (phy_mask & BLE_PHY_MASK_2M) {
625 phy = BLE_PHY_2M;
626 phy_mask &= ~BLE_PHY_MASK_2M;
627 } else if (phy_mask & BLE_PHY_MASK_CODED) {
628 phy = BLE_PHY_CODED;
629 phy_mask &= ~BLE_PHY_MASK_CODED;
630 } else {
631 phy = 0;
632 }
633
634 if (phy_mask != 0) {
635 phy = 0;
636 }
637
638 return phy;
639 }
640
641 /**
642 *
643 * There is probably a better way for the controller to choose which PHY use.
644 * There are no BER metrics and RSSI does not give you S/N so for now we will
645 * choose this heirarchy:
646 * -> if 2Mbps available, use it.
647 * -> If 1Mbps available, use it.
648 * -> otherwise use coded phy.
649 *
650 * @param prefs The mask of preferred phys
651 * @return uint8_t The phy to use (not a mask)
652 */
653 static uint8_t
ble_ll_ctrl_find_new_phy(uint8_t phy_mask_prefs)654 ble_ll_ctrl_find_new_phy(uint8_t phy_mask_prefs)
655 {
656 uint8_t new_phy;
657
658 new_phy = phy_mask_prefs;
659 if (new_phy) {
660 if (new_phy & BLE_PHY_MASK_2M) {
661 new_phy = BLE_PHY_2M;
662 } else if (new_phy & BLE_PHY_MASK_1M) {
663 new_phy = BLE_PHY_1M;
664 } else {
665 new_phy = BLE_PHY_CODED;
666 }
667 }
668
669 return new_phy;
670 }
671
672 /**
673 * Create a LL_PHY_UPDATE_IND pdu
674 *
675 * @param connsm Pointer to connection state machine
676 * @param dptr Pointer to PHY_REQ or PHY_RSP data.
677 * @param ctrdata: Pointer to where CtrData of UPDATE_IND pdu starts
678 * @param slave_req flag denoting if slave requested this. 0: no 1:yes
679 */
680 static void
ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm * connsm,uint8_t * dptr,uint8_t * ctrdata,int slave_req)681 ble_ll_ctrl_phy_update_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
682 uint8_t *ctrdata, int slave_req)
683 {
684 uint8_t m_to_s;
685 uint8_t s_to_m;
686 uint8_t tx_phys;
687 uint8_t rx_phys;
688 uint16_t instant;
689
690 /* Get preferences from PDU */
691 tx_phys = dptr[0];
692 rx_phys = dptr[1];
693
694 /* Get m_to_s and s_to_m masks */
695 if (slave_req) {
696 m_to_s = connsm->phy_data.host_pref_tx_phys_mask & rx_phys;
697 s_to_m = connsm->phy_data.host_pref_rx_phys_mask & tx_phys;
698 } else {
699 m_to_s = connsm->phy_data.req_pref_tx_phys_mask & rx_phys;
700 s_to_m = connsm->phy_data.req_pref_rx_phys_mask & tx_phys;
701 }
702
703 /* Find new phys. If not different than current, set to 0 */
704 m_to_s = ble_ll_ctrl_find_new_phy(m_to_s);
705 if (m_to_s == connsm->phy_data.cur_tx_phy) {
706 m_to_s = 0;
707 }
708
709 s_to_m = ble_ll_ctrl_find_new_phy(s_to_m);
710 if (s_to_m == connsm->phy_data.cur_rx_phy) {
711 s_to_m = 0;
712 }
713
714 /* At this point, m_to_s and s_to_m are not masks; they are numeric */
715
716 /*
717 * If not changing we still send update ind. Check if hosts expects
718 * the event and if so send it. Stop control procedure if it is the
719 * one running.
720 */
721 if ((m_to_s == 0) && (s_to_m == 0)) {
722 if (CONN_F_PEER_PHY_UPDATE(connsm)) {
723 CONN_F_PEER_PHY_UPDATE(connsm) = 0;
724 } else if (CONN_F_CTRLR_PHY_UPDATE(connsm)) {
725 CONN_F_CTRLR_PHY_UPDATE(connsm) = 0;
726 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
727 } else {
728 ble_ll_hci_ev_phy_update(connsm, BLE_ERR_SUCCESS);
729 CONN_F_HOST_PHY_UPDATE(connsm) = 0;
730 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
731 }
732 instant = 0;
733 } else {
734 /* Determine instant we will use. 6 more is minimum */
735 instant = connsm->event_cntr + connsm->slave_latency + 6 + 1;
736 connsm->phy_instant = instant;
737 CONN_F_PHY_UPDATE_SCHED(connsm) = 1;
738
739 /* Set new phys to use when instant occurs */
740 connsm->phy_data.new_tx_phy = m_to_s;
741 connsm->phy_data.new_rx_phy = s_to_m;
742
743 /* Convert m_to_s and s_to_m to masks */
744 if (m_to_s) {
745 m_to_s = 1 << (m_to_s - 1);
746 }
747
748 if (s_to_m) {
749 s_to_m = 1 << (s_to_m - 1);
750 }
751 }
752
753 ctrdata[0] = m_to_s;
754 ctrdata[1] = s_to_m;
755 put_le16(ctrdata + 2, instant);
756 }
757
758 /**
759 * Create a LL_PHY_REQ or LL_PHY_RSP pdu
760 *
761 * @param connsm Pointer to connection state machine
762 * @param ctrdata: Pointer to where CtrData starts in pdu
763 */
764 static void
ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm * connsm,uint8_t * ctrdata)765 ble_ll_ctrl_phy_req_rsp_make(struct ble_ll_conn_sm *connsm, uint8_t *ctrdata)
766 {
767 /* If no preference we use current phy */
768 if (connsm->phy_data.host_pref_tx_phys_mask == 0) {
769 ctrdata[0] = CONN_CUR_TX_PHY_MASK(connsm);
770 } else {
771 ctrdata[0] = connsm->phy_data.host_pref_tx_phys_mask;
772 }
773 if (connsm->phy_data.host_pref_rx_phys_mask == 0) {
774 ctrdata[1] = CONN_CUR_RX_PHY_MASK(connsm);
775 } else {
776 ctrdata[1] = connsm->phy_data.host_pref_rx_phys_mask;
777 }
778 }
779
780 static uint8_t
ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm * connsm,uint8_t * req,uint8_t * rsp)781 ble_ll_ctrl_rx_phy_req(struct ble_ll_conn_sm *connsm, uint8_t *req,
782 uint8_t *rsp)
783 {
784 uint8_t rsp_opcode;
785 uint8_t err;
786
787 /*
788 * XXX: TODO if we have an instant in progress we should end connection.
789 * At least it seems that is the case. Need to figure out more from
790 * the spec here.
791 */
792
793 /* Check if we have already initiated a procedure with an instant */
794 err = ble_ll_ctrl_proc_with_instant_initiated(connsm,
795 BLE_LL_CTRL_PROC_PHY_UPDATE);
796
797 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
798 if (err) {
799 ble_ll_ctrl_rej_ext_ind_make(BLE_LL_CTRL_PHY_REQ, err, rsp);
800 rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT;
801 } else {
802 /*
803 * NOTE: do not change order of these two lines as the call to
804 * make the LL_PHY_UPDATE_IND pdu might clear the flag.
805 */
806 CONN_F_PEER_PHY_UPDATE(connsm) = 1;
807 ble_ll_ctrl_phy_update_ind_make(connsm, req, rsp, 1);
808 rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND;
809 }
810 } else {
811 /* XXX: deal with other control procedures that we need to stop */
812 if (err) {
813 if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) {
814 ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer);
815 connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE;
816 }
817
818 /* If there is a PHY update procedure pending cancel it */
819 ble_ll_ctrl_phy_update_cancel(connsm, err);
820
821 /* XXX: ? Should not be any phy update events */
822 CONN_F_PHY_UPDATE_EVENT(connsm) = 0;
823 }
824
825 /* XXX: TODO: if we started another procedure with an instant
826 * why are we doing this? Need to look into this.*/
827
828 /* Respond to master's phy update procedure */
829 CONN_F_PEER_PHY_UPDATE(connsm) = 1;
830 ble_ll_ctrl_phy_req_rsp_make(connsm, rsp);
831 rsp_opcode = BLE_LL_CTRL_PHY_RSP;
832
833 if (rsp[0] & BLE_PHY_MASK_1M) {
834 connsm->phy_tx_transition = BLE_PHY_1M;
835 } else if (rsp[0] & BLE_PHY_MASK_2M) {
836 connsm->phy_tx_transition = BLE_PHY_2M;
837 } else if (rsp[0] & BLE_PHY_MASK_CODED) {
838 connsm->phy_tx_transition = BLE_PHY_CODED;
839 }
840
841 /* Start response timer */
842 connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_PHY_UPDATE;
843 ble_ll_ctrl_start_rsp_timer(connsm);
844 }
845 return rsp_opcode;
846 }
847
848 /**
849 * Process a received LL_PHY_RSP pdu
850 *
851 * @param connsm
852 * @param dptr Pointer to LL_PHY_RSP ctrdata
853 * @param rsp Pointer to CtrData of PHY_UPDATE_IND.
854 *
855 * @return uint8_t
856 */
857 static uint8_t
ble_ll_ctrl_rx_phy_rsp(struct ble_ll_conn_sm * connsm,uint8_t * dptr,uint8_t * rsp)858 ble_ll_ctrl_rx_phy_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
859 uint8_t *rsp)
860 {
861 uint8_t rsp_opcode;
862
863 rsp_opcode = BLE_ERR_MAX;
864 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
865 if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) {
866 ble_ll_ctrl_phy_update_ind_make(connsm, dptr, rsp, 0);
867 ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer);
868 rsp_opcode = BLE_LL_CTRL_PHY_UPDATE_IND;
869 }
870
871 /*
872 * If not in the process of doing this control procedure something
873 * is wrong. End connection? Assert?
874 *
875 * XXX: TODO count some stat?
876 */
877 } else {
878 rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP;
879 }
880
881 /* NOTE: slave should never receive one of these */
882
883 return rsp_opcode;
884 }
885
886 /**
887 * Called when a LL_PHY_UPDATE_IND pdu is received
888 *
889 * NOTE: slave is the only device that should receive this.
890 *
891 * @param connsm
892 * @param dptr
893 *
894 * @return uint8_t
895 */
896 static uint8_t
ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm * connsm,uint8_t * dptr)897 ble_ll_ctrl_rx_phy_update_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
898 {
899 int no_change;
900 uint8_t new_m_to_s_mask;
901 uint8_t new_s_to_m_mask;
902 uint8_t new_tx_phy;
903 uint8_t new_rx_phy;
904 uint16_t instant;
905 uint16_t delta;
906
907 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
908 return BLE_LL_CTRL_UNKNOWN_RSP;
909 }
910
911 /*
912 * Reception stops the procedure response timer but does not
913 * complete the procedure
914 */
915 if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_PHY_UPDATE) {
916 ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer);
917 }
918
919 /*
920 * XXX: Should we check to see if we are expecting to receive one
921 * of these, and if not, kill connection? Meaning we better be
922 * doing either a PEER, CTRLR, or HOST phy update.
923 */
924 /* get the new phy masks and see if we need to change */
925 new_m_to_s_mask = dptr[0];
926 new_s_to_m_mask = dptr[1];
927 instant = get_le16(dptr + 2);
928
929 if ((new_m_to_s_mask == 0) && (new_s_to_m_mask == 0)) {
930 /* No change in phy */
931 no_change = 1;
932 } else {
933 no_change = 0;
934 /*
935 * NOTE: from the slaves perspective, the m to s phy is the one
936 * that the slave will receive on; s to m is the one it will
937 * transmit on
938 */
939 new_rx_phy = ble_ll_ctrl_phy_from_phy_mask(new_m_to_s_mask);
940 new_tx_phy = ble_ll_ctrl_phy_from_phy_mask(new_s_to_m_mask);
941
942 if ((new_tx_phy == 0) && (new_rx_phy == 0)) {
943 /* XXX: this is an error! What to do??? */
944 no_change = 1;
945 }
946
947 if ((new_tx_phy == connsm->phy_data.cur_tx_phy) &&
948 (new_rx_phy == connsm->phy_data.cur_rx_phy)) {
949 no_change = 1;
950 }
951 }
952
953 if (!no_change) {
954 /* If instant is in the past, we have to end the connection */
955 delta = (instant - connsm->event_cntr) & 0xFFFF;
956 if (delta >= 32767) {
957 ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED);
958 } else {
959 connsm->phy_data.new_tx_phy = new_tx_phy;
960 connsm->phy_data.new_rx_phy = new_rx_phy;
961 connsm->phy_instant = instant;
962 CONN_F_PHY_UPDATE_SCHED(connsm) = 1;
963 }
964 return BLE_ERR_MAX;
965 }
966
967 ble_ll_ctrl_phy_update_proc_complete(connsm);
968
969 return BLE_ERR_MAX;
970 }
971 #endif
972
973 /**
974 * Create a link layer length request or length response PDU.
975 *
976 * NOTE: this function does not set the LL data pdu header nor does it
977 * set the opcode in the buffer.
978 *
979 * @param connsm
980 * @param dptr: Pointer to where control pdu payload starts
981 */
982 static void
ble_ll_ctrl_datalen_upd_make(struct ble_ll_conn_sm * connsm,uint8_t * dptr)983 ble_ll_ctrl_datalen_upd_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
984 {
985 put_le16(dptr + 1, connsm->max_rx_octets);
986 put_le16(dptr + 3, connsm->max_rx_time);
987 put_le16(dptr + 5, connsm->max_tx_octets);
988 put_le16(dptr + 7, connsm->max_tx_time);
989 }
990
991 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
992 void
ble_ll_calc_session_key(struct ble_ll_conn_sm * connsm)993 ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm)
994 {
995 #ifdef BLE_LL_ENCRYPT_DEBUG
996 int cnt;
997 #endif
998
999 /* XXX: possibly have some way out of this if this locks up */
1000 while (1) {
1001 if (!ble_hw_encrypt_block(&connsm->enc_data.enc_block)) {
1002 break;
1003 }
1004 }
1005
1006 #ifdef BLE_LL_ENCRYPT_DEBUG
1007 console_printf("Calculating Session Key for handle=%u",
1008 connsm->conn_handle);
1009
1010 console_printf("\nLTK:");
1011 for (cnt = 0; cnt < 16; ++cnt) {
1012 console_printf("%02x", connsm->enc_data.enc_block.key[cnt]);
1013 }
1014 console_printf("\nSKD:");
1015 for (cnt = 0; cnt < 16; ++cnt) {
1016 console_printf("%02x", connsm->enc_data.enc_block.plain_text[cnt]);
1017 }
1018 console_printf("\nSession Key:");
1019 for (cnt = 0; cnt < 16; ++cnt) {
1020 console_printf("%02x", connsm->enc_data.enc_block.cipher_text[cnt]);
1021 }
1022 console_printf("\nIV:");
1023 for (cnt = 0; cnt < 8; ++ cnt) {
1024 console_printf("%02x", connsm->enc_data.iv[cnt]);
1025 }
1026 console_printf("\n");
1027 #endif
1028 }
1029
1030 /**
1031 * Called to determine if this is a control PDU we are allowed to send. This
1032 * is called when a link is being encrypted, as only certain control PDU's
1033 * area lowed to be sent.
1034 *
1035 * XXX: the current code may actually allow some control pdu's to be sent
1036 * in states where they shouldnt. I dont expect those states to occur so I
1037 * dont try to check for them but we could do more... for example there are
1038 * different PDUs allowed for master/slave and TX/RX
1039 *
1040 * @param llid
1041 * @param opcode
1042 * @param len
1043 *
1044 * @return int
1045 */
1046 static int
ble_ll_ctrl_enc_allowed_pdu(uint8_t llid,uint8_t len,uint8_t opcode)1047 ble_ll_ctrl_enc_allowed_pdu(uint8_t llid, uint8_t len, uint8_t opcode)
1048 {
1049 int allowed;
1050
1051 allowed = 0;
1052
1053 switch (llid) {
1054 case BLE_LL_LLID_CTRL:
1055 switch (opcode) {
1056 case BLE_LL_CTRL_REJECT_IND:
1057 case BLE_LL_CTRL_REJECT_IND_EXT:
1058 case BLE_LL_CTRL_START_ENC_RSP:
1059 case BLE_LL_CTRL_START_ENC_REQ:
1060 case BLE_LL_CTRL_ENC_REQ:
1061 case BLE_LL_CTRL_ENC_RSP:
1062 case BLE_LL_CTRL_PAUSE_ENC_REQ:
1063 case BLE_LL_CTRL_PAUSE_ENC_RSP:
1064 case BLE_LL_CTRL_TERMINATE_IND:
1065 allowed = 1;
1066 break;
1067 }
1068 break;
1069 case BLE_LL_LLID_DATA_FRAG:
1070 if (len == 0) {
1071 /* Empty PDUs are allowed */
1072 allowed = 1;
1073 }
1074 break;
1075 }
1076
1077 return allowed;
1078 }
1079
1080 int
ble_ll_ctrl_enc_allowed_pdu_rx(struct os_mbuf * rxpdu)1081 ble_ll_ctrl_enc_allowed_pdu_rx(struct os_mbuf *rxpdu)
1082 {
1083 uint8_t llid;
1084 uint8_t len;
1085 uint8_t opcode;
1086
1087 llid = rxpdu->om_data[0] & BLE_LL_DATA_HDR_LLID_MASK;
1088 len = rxpdu->om_data[1];
1089 if (llid == BLE_LL_LLID_CTRL) {
1090 opcode = rxpdu->om_data[2];
1091 } else {
1092 opcode = 0;
1093 }
1094
1095 return ble_ll_ctrl_enc_allowed_pdu(llid, len, opcode);
1096 }
1097
1098 int
ble_ll_ctrl_enc_allowed_pdu_tx(struct os_mbuf_pkthdr * pkthdr)1099 ble_ll_ctrl_enc_allowed_pdu_tx(struct os_mbuf_pkthdr *pkthdr)
1100 {
1101 struct os_mbuf *m;
1102 struct ble_mbuf_hdr *ble_hdr;
1103 uint8_t llid;
1104 uint8_t len;
1105 uint8_t opcode;
1106
1107 m = OS_MBUF_PKTHDR_TO_MBUF(pkthdr);
1108 ble_hdr = BLE_MBUF_HDR_PTR(m);
1109
1110 llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK;
1111 len = ble_hdr->txinfo.pyld_len;
1112 if (llid == BLE_LL_LLID_CTRL) {
1113 opcode = m->om_data[0];
1114 } else {
1115 opcode = 0;
1116 }
1117
1118 return ble_ll_ctrl_enc_allowed_pdu(llid, len, opcode);
1119 }
1120
1121 int
ble_ll_ctrl_is_start_enc_rsp(struct os_mbuf * txpdu)1122 ble_ll_ctrl_is_start_enc_rsp(struct os_mbuf *txpdu)
1123 {
1124 int is_start_enc_rsp;
1125 uint8_t opcode;
1126 uint8_t llid;
1127 struct ble_mbuf_hdr *ble_hdr;
1128
1129 is_start_enc_rsp = 0;
1130 ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
1131
1132 llid = ble_hdr->txinfo.hdr_byte & BLE_LL_DATA_HDR_LLID_MASK;
1133 if (llid == BLE_LL_LLID_CTRL) {
1134 opcode = txpdu->om_data[0];
1135 if (opcode == BLE_LL_CTRL_START_ENC_RSP) {
1136 is_start_enc_rsp = 1;
1137 }
1138 }
1139
1140 return is_start_enc_rsp;
1141 }
1142
1143 /**
1144 * Called to create and send a LL_START_ENC_REQ
1145 *
1146 * @param connsm
1147 * @param err
1148 *
1149 * @return int
1150 */
1151 int
ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm * connsm)1152 ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm)
1153 {
1154 int rc;
1155 struct os_mbuf *om;
1156
1157 om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN,
1158 sizeof(struct ble_mbuf_hdr));
1159 if (om) {
1160 om->om_data[0] = BLE_LL_CTRL_START_ENC_REQ;
1161 ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, 1);
1162
1163 /* Wait for LL_START_ENC_RSP */
1164 connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_ENCRYPT;
1165 ble_ll_ctrl_start_rsp_timer(connsm);
1166
1167 rc = 0;
1168 } else {
1169 rc = -1;
1170 }
1171 return rc;
1172 }
1173
1174 /**
1175 * Create a link layer control "encrypt request" PDU.
1176 *
1177 * The LL_ENC_REQ PDU format is:
1178 * Rand (8)
1179 * EDIV (2)
1180 * SKDm (8)
1181 * IVm (4)
1182 *
1183 * The random number and encrypted diversifier come from the host command.
1184 * Controller generates master portion of SDK and IV.
1185 *
1186 * NOTE: this function does not set the LL data pdu header nor does it
1187 * set the opcode in the buffer.
1188 *
1189 * @param connsm
1190 * @param dptr: Pointer to where control pdu payload starts
1191 */
1192 static void
ble_ll_ctrl_enc_req_make(struct ble_ll_conn_sm * connsm,uint8_t * dptr)1193 ble_ll_ctrl_enc_req_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
1194 {
1195 put_le64(dptr, connsm->enc_data.host_rand_num);
1196 put_le16(dptr + 8, connsm->enc_data.enc_div);
1197
1198 #ifdef BLE_LL_ENCRYPT_USE_TEST_DATA
1199 /* IV stored LSB to MSB, IVm is LSB, IVs is MSB */
1200 put_le64(dptr + 10, g_bletest_SKDm);
1201 swap_buf(connsm->enc_data.enc_block.plain_text + 8, dptr + 10, 8);
1202 put_le32(dptr + 18, g_bletest_IVm);
1203 memcpy(connsm->enc_data.iv, dptr + 18, 4);
1204 return;
1205 #endif
1206
1207 ble_ll_rand_data_get(connsm->enc_data.enc_block.plain_text + 8, 8);
1208 swap_buf(dptr + 10, connsm->enc_data.enc_block.plain_text + 8, 8);
1209 ble_ll_rand_data_get(connsm->enc_data.iv, 4);
1210 memcpy(dptr + 18, connsm->enc_data.iv, 4);
1211 }
1212
1213 /**
1214 * Called when LL_ENC_RSP is received by the master.
1215 *
1216 * Context: Link Layer Task.
1217 *
1218 * Format of the LL_ENC_RSP is:
1219 * SKDs (8)
1220 * IVs (4)
1221 *
1222 * The master now has the long term key (from the start encrypt command)
1223 * and the SKD (stored in the plain text encryption block). From this the
1224 * sessionKey is generated.
1225 *
1226 * @param connsm
1227 * @param dptr
1228 */
1229 static void
ble_ll_ctrl_rx_enc_rsp(struct ble_ll_conn_sm * connsm,uint8_t * dptr)1230 ble_ll_ctrl_rx_enc_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
1231 {
1232 /* Calculate session key now that we have received the ENC_RSP */
1233 if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_ENCRYPT) {
1234 /* In case we were already encrypted we need to reset packet counters */
1235 connsm->enc_data.rx_pkt_cntr = 0;
1236 connsm->enc_data.tx_pkt_cntr = 0;
1237 connsm->enc_data.tx_encrypted = 0;
1238
1239 swap_buf(connsm->enc_data.enc_block.plain_text, dptr, 8);
1240 memcpy(connsm->enc_data.iv + 4, dptr + 8, 4);
1241 ble_ll_calc_session_key(connsm);
1242 connsm->enc_data.enc_state = CONN_ENC_S_START_ENC_REQ_WAIT;
1243 }
1244 }
1245
1246 /**
1247 * Called when we have received a LL control encryption request PDU. This
1248 * should only be received by a slave.
1249 *
1250 * The LL_ENC_REQ PDU format is:
1251 * Rand (8)
1252 * EDIV (2)
1253 * SKDm (8)
1254 * IVm (4)
1255 *
1256 * This function returns the response opcode. Typically this will be ENC_RSP
1257 * but it could be a reject ind. Note that the caller of this function
1258 * will send the REJECT_IND_EXT if supported by remote.
1259 *
1260 * NOTE: if this is received by a master we will silently discard the PDU
1261 * (denoted by return BLE_ERR_MAX).
1262 *
1263 * @param connsm
1264 * @param dptr Pointer to start of encrypt request data.
1265 * @param rspbuf
1266 */
1267 static uint8_t
ble_ll_ctrl_rx_enc_req(struct ble_ll_conn_sm * connsm,uint8_t * dptr,uint8_t * rspdata)1268 ble_ll_ctrl_rx_enc_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
1269 uint8_t *rspdata)
1270 {
1271 if (connsm->conn_role != BLE_LL_CONN_ROLE_SLAVE) {
1272 return BLE_LL_CTRL_UNKNOWN_RSP;
1273 }
1274
1275 /* In case we were already encrypted we need to reset packet counters */
1276 connsm->enc_data.rx_pkt_cntr = 0;
1277 connsm->enc_data.tx_pkt_cntr = 0;
1278 connsm->enc_data.tx_encrypted = 0;
1279
1280 /* Extract information from request */
1281 connsm->enc_data.host_rand_num = get_le64(dptr);
1282 connsm->enc_data.enc_div = get_le16(dptr + 8);
1283
1284 #if BLE_LL_ENCRYPT_USE_TEST_DATA
1285 swap_buf(connsm->enc_data.enc_block.plain_text + 8, dptr + 10, 8);
1286 memcpy(connsm->enc_data.iv, dptr + 18, 4);
1287
1288 put_le64(rspdata, g_bletest_SKDs);
1289 swap_buf(connsm->enc_data.enc_block.plain_text, rspdata, 8);
1290 put_le32(rspdata + 8, g_bletest_IVs);
1291 memcpy(connsm->enc_data.iv + 4, rspdata + 8, 4);
1292 return BLE_LL_CTRL_ENC_RSP;
1293 #endif
1294
1295 swap_buf(connsm->enc_data.enc_block.plain_text + 8, dptr + 10, 8);
1296 memcpy(connsm->enc_data.iv, dptr + 18, 4);
1297
1298 /* Create the ENC_RSP. Concatenate our SKD and IV */
1299 ble_ll_rand_data_get(connsm->enc_data.enc_block.plain_text, 8);
1300 swap_buf(rspdata, connsm->enc_data.enc_block.plain_text, 8);
1301 ble_ll_rand_data_get(connsm->enc_data.iv + 4, 4);
1302 memcpy(rspdata + 8, connsm->enc_data.iv + 4, 4);
1303
1304 return BLE_LL_CTRL_ENC_RSP;
1305 }
1306
1307 static uint8_t
ble_ll_ctrl_rx_start_enc_req(struct ble_ll_conn_sm * connsm)1308 ble_ll_ctrl_rx_start_enc_req(struct ble_ll_conn_sm *connsm)
1309 {
1310 int rc;
1311
1312 /* Only master should receive start enc request */
1313 rc = BLE_ERR_MAX;
1314 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
1315 /* We only want to send a START_ENC_RSP if we havent yet */
1316 if (connsm->enc_data.enc_state == CONN_ENC_S_START_ENC_REQ_WAIT) {
1317 connsm->enc_data.enc_state = CONN_ENC_S_START_ENC_RSP_WAIT;
1318 rc = BLE_LL_CTRL_START_ENC_RSP;
1319 }
1320 } else {
1321 rc = BLE_LL_CTRL_UNKNOWN_RSP;
1322 }
1323 return rc;
1324 }
1325
1326 static uint8_t
ble_ll_ctrl_rx_pause_enc_req(struct ble_ll_conn_sm * connsm)1327 ble_ll_ctrl_rx_pause_enc_req(struct ble_ll_conn_sm *connsm)
1328 {
1329 int rc;
1330
1331 /*
1332 * The spec does not say what to do here, but if we receive a pause
1333 * encryption request and we are not encrypted, what do we do? We
1334 * ignore it...
1335 */
1336 rc = BLE_ERR_MAX;
1337 if ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) &&
1338 (connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED)) {
1339 rc = BLE_LL_CTRL_PAUSE_ENC_RSP;
1340 } else {
1341 rc = BLE_LL_CTRL_UNKNOWN_RSP;
1342 }
1343
1344 return rc;
1345 }
1346
1347 /**
1348 * Called when a LL control pdu with opcode PAUSE_ENC_RSP is received.
1349 *
1350 *
1351 * @param connsm
1352 *
1353 * @return uint8_t
1354 */
1355 static uint8_t
ble_ll_ctrl_rx_pause_enc_rsp(struct ble_ll_conn_sm * connsm)1356 ble_ll_ctrl_rx_pause_enc_rsp(struct ble_ll_conn_sm *connsm)
1357 {
1358 int rc;
1359
1360 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
1361 rc = BLE_LL_CTRL_PAUSE_ENC_RSP;
1362 } else {
1363 rc = BLE_LL_CTRL_UNKNOWN_RSP;
1364 }
1365
1366 return rc;
1367 }
1368
1369 /**
1370 * Called when we have received a LL_CTRL_START_ENC_RSP.
1371 *
1372 * Context: Link-layer task
1373 *
1374 * @param connsm
1375 *
1376 * @return uint8_t
1377 */
1378 static uint8_t
ble_ll_ctrl_rx_start_enc_rsp(struct ble_ll_conn_sm * connsm)1379 ble_ll_ctrl_rx_start_enc_rsp(struct ble_ll_conn_sm *connsm)
1380 {
1381 int rc;
1382
1383 /* Not in proper state. Discard */
1384 if (connsm->enc_data.enc_state != CONN_ENC_S_START_ENC_RSP_WAIT) {
1385 return BLE_ERR_MAX;
1386 }
1387
1388 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT);
1389
1390 /* If master, we are done. Stop control procedure and sent event to host */
1391 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
1392 /* We are encrypted */
1393 connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED;
1394 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) == 1)
1395 ble_ll_conn_auth_pyld_timer_start(connsm);
1396 #endif
1397 rc = BLE_ERR_MAX;
1398 } else {
1399 /* Procedure has completed but slave needs to send START_ENC_RSP */
1400 rc = BLE_LL_CTRL_START_ENC_RSP;
1401 }
1402
1403 /*
1404 * XXX: for now, a Slave sends this event when it receivest the
1405 * START_ENC_RSP from the master. It might be technically incorrect
1406 * to send it before we transmit our own START_ENC_RSP.
1407 */
1408 ble_ll_hci_ev_encrypt_chg(connsm, BLE_ERR_SUCCESS);
1409
1410 return rc;
1411 }
1412
1413 #endif
1414
1415 /**
1416 * Called to make a connection parameter request or response control pdu.
1417 *
1418 * @param connsm
1419 * @param dptr Pointer to start of data. NOTE: the opcode is not part
1420 * of the data.
1421 */
1422 static void
ble_ll_ctrl_conn_param_pdu_make(struct ble_ll_conn_sm * connsm,uint8_t * dptr,struct ble_ll_conn_params * req)1423 ble_ll_ctrl_conn_param_pdu_make(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
1424 struct ble_ll_conn_params *req)
1425 {
1426 uint16_t offset;
1427 struct hci_conn_update *hcu;
1428
1429 /* If we were passed in a request, we use the parameters from the request */
1430 if (req) {
1431 put_le16(dptr, req->interval_min);
1432 put_le16(dptr + 2, req->interval_max);
1433 put_le16(dptr + 4, req->latency);
1434 put_le16(dptr + 6, req->timeout);
1435 } else {
1436 hcu = &connsm->conn_param_req;
1437 /* The host should have provided the parameters! */
1438 BLE_LL_ASSERT(hcu->handle != 0);
1439 put_le16(dptr, hcu->conn_itvl_min);
1440 put_le16(dptr + 2, hcu->conn_itvl_max);
1441 put_le16(dptr + 4, hcu->conn_latency);
1442 put_le16(dptr + 6, hcu->supervision_timeout);
1443 }
1444
1445 /* XXX: NOTE: if interval min and interval max are != to each
1446 * other this value should be set to non-zero. I think this
1447 * applies only when an offset field is set. See section 5.1.7.1 pg 103
1448 * Vol 6 Part B.
1449 */
1450 /* XXX: for now, set periodicity to 0 */
1451 dptr[8] = 0;
1452
1453 /* XXX: deal with reference event count. what to put here? */
1454 put_le16(dptr + 9, connsm->event_cntr);
1455
1456 /* XXX: For now, dont use offsets */
1457 offset = 0xFFFF;
1458 put_le16(dptr + 11, offset);
1459 put_le16(dptr + 13, offset);
1460 put_le16(dptr + 15, offset);
1461 put_le16(dptr + 17, offset);
1462 put_le16(dptr + 19, offset);
1463 put_le16(dptr + 21, offset);
1464 }
1465
1466 static void
ble_ll_ctrl_version_ind_make(struct ble_ll_conn_sm * connsm,uint8_t * pyld)1467 ble_ll_ctrl_version_ind_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld)
1468 {
1469 /* Set flag to denote we have sent/received this */
1470 connsm->csmflags.cfbit.version_ind_sent = 1;
1471
1472 /* Fill out response */
1473 pyld[0] = BLE_HCI_VER_BCS_5_0;
1474 put_le16(pyld + 1, MYNEWT_VAL(BLE_LL_MFRG_ID));
1475 put_le16(pyld + 3, BLE_LL_SUB_VERS_NR);
1476 }
1477
1478 /**
1479 * Called to make a LL control channel map request PDU.
1480 *
1481 * @param connsm Pointer to connection state machine
1482 * @param pyld Pointer to payload of LL control PDU
1483 */
1484 static void
ble_ll_ctrl_chanmap_req_make(struct ble_ll_conn_sm * connsm,uint8_t * pyld)1485 ble_ll_ctrl_chanmap_req_make(struct ble_ll_conn_sm *connsm, uint8_t *pyld)
1486 {
1487 /* Copy channel map that host desires into request */
1488 memcpy(pyld, g_ble_ll_conn_params.master_chan_map, BLE_LL_CONN_CHMAP_LEN);
1489 memcpy(connsm->req_chanmap, pyld, BLE_LL_CONN_CHMAP_LEN);
1490
1491 /* Place instant into request */
1492 connsm->chanmap_instant = connsm->event_cntr + connsm->slave_latency + 6 + 1;
1493 put_le16(pyld + BLE_LL_CONN_CHMAP_LEN, connsm->chanmap_instant);
1494
1495 /* Set scheduled flag */
1496 connsm->csmflags.cfbit.chanmap_update_scheduled = 1;
1497 }
1498
1499 /**
1500 * Called to respond to a LL control PDU connection parameter request or
1501 * response.
1502 *
1503 * @param connsm
1504 * @param rsp
1505 * @param req
1506 *
1507 * @return uint8_t
1508 */
1509 uint8_t
ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm * connsm,uint8_t * rsp,struct ble_ll_conn_params * req)1510 ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm, uint8_t *rsp,
1511 struct ble_ll_conn_params *req)
1512 {
1513 uint8_t rsp_opcode;
1514
1515 if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
1516 /* Create a connection parameter response */
1517 ble_ll_ctrl_conn_param_pdu_make(connsm, rsp + 1, req);
1518 rsp_opcode = BLE_LL_CTRL_CONN_PARM_RSP;
1519 } else {
1520 /* Create a connection update pdu */
1521 ble_ll_ctrl_conn_upd_make(connsm, rsp + 1, req);
1522 rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND;
1523 }
1524
1525 return rsp_opcode;
1526 }
1527
1528 /**
1529 * Called when we have received a LL_REJECT_IND or LL_REJECT_IND_EXT link
1530 * layer control Data Channel pdu.
1531 *
1532 * @param connsm
1533 * @param dptr
1534 * @param opcode
1535 */
1536 static int
ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm * connsm,uint8_t * dptr,uint8_t opcode,uint8_t * rspdata)1537 ble_ll_ctrl_rx_reject_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
1538 uint8_t opcode, uint8_t *rspdata)
1539 {
1540 uint8_t ble_error;
1541 uint8_t rsp_opcode = BLE_ERR_MAX;
1542
1543 /* Get error out of received PDU */
1544 if (opcode == BLE_LL_CTRL_REJECT_IND) {
1545 ble_error = dptr[0];
1546 } else {
1547 ble_error = dptr[1];
1548 }
1549
1550 /* XXX: should I check to make sure the rejected opcode is sane
1551 if we receive ind ext? */
1552 switch (connsm->cur_ctrl_proc) {
1553 case BLE_LL_CTRL_PROC_CONN_PARAM_REQ:
1554 if (opcode == BLE_LL_CTRL_REJECT_IND_EXT) {
1555 /* As a master we should send connection update indication in this point */
1556 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
1557 rsp_opcode = BLE_LL_CTRL_CONN_UPDATE_IND;
1558 ble_ll_ctrl_conn_upd_make(connsm, rspdata, NULL);
1559 connsm->reject_reason = BLE_ERR_SUCCESS;
1560 } else {
1561 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ);
1562 ble_ll_hci_ev_conn_update(connsm, ble_error);
1563 }
1564 }
1565 break;
1566 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
1567 case BLE_LL_CTRL_PROC_ENCRYPT:
1568 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_ENCRYPT);
1569 ble_ll_hci_ev_encrypt_chg(connsm, ble_error);
1570 connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED;
1571 break;
1572 #endif
1573 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
1574 case BLE_LL_CTRL_PROC_PHY_UPDATE:
1575 ble_ll_ctrl_phy_update_cancel(connsm, ble_error);
1576 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_PHY_UPDATE);
1577 break;
1578 #endif
1579 case BLE_LL_CTRL_PROC_DATA_LEN_UPD:
1580 /* That should not happen according to Bluetooth 5.0 Vol6 Part B, 5.1.9
1581 * However we need this workaround as there are devices on the market
1582 * which do send LL_REJECT on LL_LENGTH_REQ when collision happens
1583 */
1584 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
1585 break;
1586 default:
1587 break;
1588 }
1589
1590 return rsp_opcode;
1591 }
1592
1593 /**
1594 * Called when we receive a connection update event
1595 *
1596 * @param connsm
1597 * @param dptr
1598 *
1599 * @return int
1600 */
1601 static int
ble_ll_ctrl_rx_conn_update(struct ble_ll_conn_sm * connsm,uint8_t * dptr)1602 ble_ll_ctrl_rx_conn_update(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
1603 {
1604 uint8_t rsp_opcode;
1605 uint16_t conn_events;
1606 struct ble_ll_conn_upd_req *reqdata;
1607
1608 /* Only a slave should receive this */
1609 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
1610 return BLE_LL_CTRL_UNKNOWN_RSP;
1611 }
1612
1613 /* Retrieve parameters */
1614 reqdata = &connsm->conn_update_req;
1615 reqdata->winsize = dptr[0];
1616 reqdata->winoffset = get_le16(dptr + 1);
1617 reqdata->interval = get_le16(dptr + 3);
1618 reqdata->latency = get_le16(dptr + 5);
1619 reqdata->timeout = get_le16(dptr + 7);
1620 reqdata->instant = get_le16(dptr + 9);
1621
1622 /* XXX: validate them at some point. If they dont check out, we
1623 return the unknown response */
1624 rsp_opcode = BLE_ERR_MAX;
1625
1626 /* If instant is in the past, we have to end the connection */
1627 conn_events = (reqdata->instant - connsm->event_cntr) & 0xFFFF;
1628 if (conn_events >= 32767) {
1629 ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED);
1630 } else {
1631 connsm->csmflags.cfbit.conn_update_sched = 1;
1632
1633 /*
1634 * Errata says that receiving a connection update when the event
1635 * counter is equal to the instant means wesimply ignore the window
1636 * offset and window size. Anchor point has already been set based on
1637 * first packet received in connection event. Given that we increment
1638 * the event counter BEFORE checking to see if the instant is equal to
1639 * the event counter what we do here is increment the instant and set
1640 * the window offset and size to 0.
1641 */
1642 if (conn_events == 0) {
1643 reqdata->winoffset = 0;
1644 reqdata->winsize = 0;
1645 reqdata->instant += 1;
1646 }
1647 }
1648
1649 return rsp_opcode;
1650 }
1651
1652 void
ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm * connsm)1653 ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm)
1654 {
1655 if (!(connsm->conn_features & BLE_LL_FEAT_DATA_LEN_EXT)) {
1656 return;
1657 }
1658
1659 /*
1660 * Section 4.5.10 Vol 6 PART B. If the max tx/rx time or octets
1661 * exceeds the minimum, data length procedure needs to occur
1662 */
1663 if ((connsm->max_tx_octets <= BLE_LL_CONN_SUPP_BYTES_MIN) &&
1664 (connsm->max_rx_octets <= BLE_LL_CONN_SUPP_BYTES_MIN) &&
1665 (connsm->max_tx_time <= BLE_LL_CONN_SUPP_TIME_MIN) &&
1666 (connsm->max_rx_time <= BLE_LL_CONN_SUPP_TIME_MIN)) {
1667 return;
1668 }
1669
1670 ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
1671 }
1672
1673 /**
1674 * Called when we receive a feature request or a slave initiated feature
1675 * request.
1676 *
1677 *
1678 * @param connsm
1679 * @param dptr
1680 * @param rspbuf
1681 * @param opcode
1682 *
1683 * @return int
1684 */
1685 static int
ble_ll_ctrl_rx_feature_req(struct ble_ll_conn_sm * connsm,uint8_t * dptr,uint8_t * rspbuf,uint8_t opcode)1686 ble_ll_ctrl_rx_feature_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
1687 uint8_t *rspbuf, uint8_t opcode)
1688 {
1689 uint8_t rsp_opcode;
1690 uint32_t our_feat;
1691
1692 /*
1693 * Only accept slave feature requests if we are a master and feature
1694 * requests if we are a slave.
1695 */
1696 if (opcode == BLE_LL_CTRL_SLAVE_FEATURE_REQ) {
1697 if (connsm->conn_role != BLE_LL_CONN_ROLE_MASTER) {
1698 return BLE_LL_CTRL_UNKNOWN_RSP;
1699 }
1700 } else {
1701 /* XXX: not sure this is correct but do it anyway */
1702 if (connsm->conn_role != BLE_LL_CONN_ROLE_SLAVE) {
1703 return BLE_LL_CTRL_UNKNOWN_RSP;
1704 }
1705 }
1706
1707 our_feat = ble_ll_read_supp_features();
1708
1709 rsp_opcode = BLE_LL_CTRL_FEATURE_RSP;
1710
1711 /*
1712 * 1st octet of features should be common features of local and remote
1713 * controller - we call this 'connection features'
1714 * remaining octets are features of controller which sends PDU, in this case
1715 * it's our controller
1716 *
1717 * See: Vol 6, Part B, section 2.4.2.10
1718 */
1719
1720 connsm->conn_features = dptr[0] & our_feat;
1721 memset(rspbuf + 1, 0, 8);
1722 put_le32(rspbuf + 1, our_feat);
1723 rspbuf[1] = connsm->conn_features;
1724
1725 /* If this is the first time we received remote features, try to start DLE */
1726 if (!connsm->csmflags.cfbit.rxd_features) {
1727 ble_ll_ctrl_initiate_dle(connsm);
1728 connsm->csmflags.cfbit.rxd_features = 1;
1729 }
1730
1731 return rsp_opcode;
1732 }
1733
1734 /**
1735 *
1736 *
1737 * Context: Link Layer task
1738 *
1739 * @param connsm
1740 * @param dptr
1741 * @param rspbuf
1742 *
1743 * @return int
1744 */
1745 static int
ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm * connsm,uint8_t * dptr,uint8_t * rspbuf)1746 ble_ll_ctrl_rx_conn_param_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
1747 uint8_t *rspbuf)
1748 {
1749 uint8_t rsp_opcode;
1750
1751 /*
1752 * This is not in the specification per se but it simplifies the
1753 * implementation. If we get a connection parameter request and we
1754 * are awaiting a reply from the host, simply ignore the request. This
1755 * might not be a good idea if the parameters are different, but oh
1756 * well. This is not expected to happen anyway. A return of BLE_ERR_MAX
1757 * means that we will simply discard the connection parameter request
1758 */
1759 if (connsm->csmflags.cfbit.awaiting_host_reply) {
1760 return BLE_ERR_MAX;
1761 }
1762
1763 /* XXX: remember to deal with this on the master: if the slave has
1764 * initiated a procedure we may have received its connection parameter
1765 * update request and have signaled the host with an event. If that
1766 * is the case, we will need to drop the host command when we get it
1767 and also clear any applicable states. */
1768
1769 /* XXX: Read 5.3 again. There are multiple control procedures that might
1770 * be pending (a connection update) that will cause collisions and the
1771 behavior below. */
1772 /*
1773 * Check for procedure collision (Vol 6 PartB 5.3). If we are a slave
1774 * and we receive a request we "consider the slave initiated
1775 * procedure as complete". This means send a connection update complete
1776 * event (with error).
1777 *
1778 * If a master, we send reject with a
1779 * transaction collision error code.
1780 */
1781 if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) {
1782 if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
1783 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ);
1784 ble_ll_hci_ev_conn_update(connsm, BLE_ERR_LMP_COLLISION);
1785 } else {
1786 /* The master sends reject ind ext w/error code 0x23 */
1787 rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT;
1788 rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ;
1789 rspbuf[2] = BLE_ERR_LMP_COLLISION;
1790 return rsp_opcode;
1791 }
1792 }
1793
1794 /*
1795 * If we are a master and we currently performing a channel map
1796 * update procedure we need to return an error
1797 */
1798 if ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) &&
1799 (connsm->csmflags.cfbit.chanmap_update_scheduled)) {
1800 rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT;
1801 rspbuf[1] = BLE_LL_CTRL_CONN_PARM_REQ;
1802 rspbuf[2] = BLE_ERR_DIFF_TRANS_COLL;
1803 return rsp_opcode;
1804 }
1805
1806 /* Process the received connection parameter request */
1807 rsp_opcode = ble_ll_ctrl_conn_param_pdu_proc(connsm, dptr, rspbuf,
1808 BLE_LL_CTRL_CONN_PARM_REQ);
1809 return rsp_opcode;
1810 }
1811
1812 static int
ble_ll_ctrl_rx_conn_param_rsp(struct ble_ll_conn_sm * connsm,uint8_t * dptr,uint8_t * rspbuf)1813 ble_ll_ctrl_rx_conn_param_rsp(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
1814 uint8_t *rspbuf)
1815 {
1816 uint8_t rsp_opcode;
1817
1818 /* A slave should never receive this response */
1819 if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
1820 return BLE_LL_CTRL_UNKNOWN_RSP;
1821 }
1822
1823 /*
1824 * This case should never happen! It means that the slave initiated a
1825 * procedure and the master initiated one as well. If we do get in this
1826 * state just clear the awaiting reply. The slave will hopefully stop its
1827 * procedure when we reply.
1828 */
1829 if (connsm->csmflags.cfbit.awaiting_host_reply) {
1830 connsm->csmflags.cfbit.awaiting_host_reply = 0;
1831 }
1832
1833 /* If we receive a response and no procedure is pending, just leave */
1834 if (!IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) {
1835 return BLE_ERR_MAX;
1836 }
1837
1838 /* Process the received connection parameter response */
1839 rsp_opcode = ble_ll_ctrl_conn_param_pdu_proc(connsm, dptr, rspbuf,
1840 BLE_LL_CTRL_CONN_PARM_RSP);
1841 return rsp_opcode;
1842 }
1843
1844 /**
1845 * Called to process the LL control PDU VERSION_IND
1846 *
1847 * Context: Link Layer task
1848 *
1849 * @param connsm
1850 * @param dptr
1851 * @param rspbuf
1852 *
1853 * @return int
1854 */
1855 static int
ble_ll_ctrl_rx_version_ind(struct ble_ll_conn_sm * connsm,uint8_t * dptr,uint8_t * rspbuf)1856 ble_ll_ctrl_rx_version_ind(struct ble_ll_conn_sm *connsm, uint8_t *dptr,
1857 uint8_t *rspbuf)
1858 {
1859 uint8_t rsp_opcode;
1860
1861 /* Process the packet */
1862 connsm->vers_nr = dptr[0];
1863 connsm->comp_id = get_le16(dptr + 1);
1864 connsm->sub_vers_nr = get_le16(dptr + 3);
1865 connsm->csmflags.cfbit.rxd_version_ind = 1;
1866
1867 rsp_opcode = BLE_ERR_MAX;
1868 if (!connsm->csmflags.cfbit.version_ind_sent) {
1869 rsp_opcode = BLE_LL_CTRL_VERSION_IND;
1870 ble_ll_ctrl_version_ind_make(connsm, rspbuf);
1871 }
1872
1873 /* Stop the control procedure */
1874 if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG)) {
1875 ble_ll_hci_ev_rd_rem_ver(connsm, BLE_ERR_SUCCESS);
1876 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_VERSION_XCHG);
1877 }
1878 return rsp_opcode;
1879 }
1880
1881 /**
1882 * Called to process a received channel map request control pdu.
1883 *
1884 * Context: Link Layer task
1885 *
1886 * @param connsm
1887 * @param dptr
1888 */
1889 static int
ble_ll_ctrl_rx_chanmap_req(struct ble_ll_conn_sm * connsm,uint8_t * dptr)1890 ble_ll_ctrl_rx_chanmap_req(struct ble_ll_conn_sm *connsm, uint8_t *dptr)
1891 {
1892 uint16_t instant;
1893 uint16_t conn_events;
1894
1895 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
1896 return BLE_LL_CTRL_UNKNOWN_RSP;
1897 }
1898
1899 /* If instant is in the past, we have to end the connection */
1900 instant = get_le16(dptr + BLE_LL_CONN_CHMAP_LEN);
1901 conn_events = (instant - connsm->event_cntr) & 0xFFFF;
1902 if (conn_events >= 32767) {
1903 ble_ll_conn_timeout(connsm, BLE_ERR_INSTANT_PASSED);
1904 } else {
1905 connsm->chanmap_instant = instant;
1906 memcpy(connsm->req_chanmap, dptr, BLE_LL_CONN_CHMAP_LEN);
1907 connsm->csmflags.cfbit.chanmap_update_scheduled = 1;
1908 }
1909
1910 return BLE_ERR_MAX;
1911 }
1912
1913 /**
1914 * Initiate LL control procedure.
1915 *
1916 * This function is called to obtain a mbuf to send a LL control PDU. The data
1917 * channel PDU header is not part of the mbuf data; it is part of the BLE
1918 * header (which is part of the mbuf).
1919 *
1920 * Context: LL task.
1921 *
1922 * @param connsm
1923 * @param ctrl_proc
1924 */
1925 static struct os_mbuf *
ble_ll_ctrl_proc_init(struct ble_ll_conn_sm * connsm,int ctrl_proc)1926 ble_ll_ctrl_proc_init(struct ble_ll_conn_sm *connsm, int ctrl_proc)
1927 {
1928 uint8_t len;
1929 uint8_t opcode;
1930 uint8_t *dptr;
1931 uint8_t *ctrdata;
1932 struct os_mbuf *om;
1933
1934 /* Get an mbuf for the control pdu */
1935 om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN, sizeof(struct ble_mbuf_hdr));
1936
1937 if (om) {
1938 /* The control data starts after the opcode (1 byte) */
1939 dptr = om->om_data;
1940 ctrdata = dptr + 1;
1941
1942 switch (ctrl_proc) {
1943 case BLE_LL_CTRL_PROC_CONN_UPDATE:
1944 opcode = BLE_LL_CTRL_CONN_UPDATE_IND;
1945 ble_ll_ctrl_conn_upd_make(connsm, ctrdata, NULL);
1946 break;
1947 case BLE_LL_CTRL_PROC_CHAN_MAP_UPD:
1948 opcode = BLE_LL_CTRL_CHANNEL_MAP_REQ;
1949 ble_ll_ctrl_chanmap_req_make(connsm, ctrdata);
1950 break;
1951 case BLE_LL_CTRL_PROC_FEATURE_XCHG:
1952 if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
1953 opcode = BLE_LL_CTRL_FEATURE_REQ;
1954 } else {
1955 opcode = BLE_LL_CTRL_SLAVE_FEATURE_REQ;
1956 }
1957 memset(ctrdata, 0, BLE_LL_CTRL_FEATURE_LEN);
1958 put_le32(ctrdata, ble_ll_read_supp_features());
1959 break;
1960 case BLE_LL_CTRL_PROC_VERSION_XCHG:
1961 opcode = BLE_LL_CTRL_VERSION_IND;
1962 ble_ll_ctrl_version_ind_make(connsm, ctrdata);
1963 break;
1964 case BLE_LL_CTRL_PROC_TERMINATE:
1965 opcode = BLE_LL_CTRL_TERMINATE_IND;
1966 ctrdata[0] = connsm->disconnect_reason;
1967 break;
1968 case BLE_LL_CTRL_PROC_CONN_PARAM_REQ:
1969 opcode = BLE_LL_CTRL_CONN_PARM_REQ;
1970 ble_ll_ctrl_conn_param_pdu_make(connsm, ctrdata, NULL);
1971 break;
1972 case BLE_LL_CTRL_PROC_LE_PING:
1973 opcode = BLE_LL_CTRL_PING_REQ;
1974 break;
1975 case BLE_LL_CTRL_PROC_DATA_LEN_UPD:
1976 opcode = BLE_LL_CTRL_LENGTH_REQ;
1977 ble_ll_ctrl_datalen_upd_make(connsm, dptr);
1978 break;
1979 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
1980 /* XXX: deal with already encrypted connection.*/
1981 case BLE_LL_CTRL_PROC_ENCRYPT:
1982 /* If we are already encrypted we do pause procedure */
1983 if (connsm->enc_data.enc_state == CONN_ENC_S_ENCRYPTED) {
1984 opcode = BLE_LL_CTRL_PAUSE_ENC_REQ;
1985 } else {
1986 opcode = BLE_LL_CTRL_ENC_REQ;
1987 ble_ll_ctrl_enc_req_make(connsm, ctrdata);
1988 }
1989 break;
1990 #endif
1991 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
1992 case BLE_LL_CTRL_PROC_PHY_UPDATE:
1993 opcode = BLE_LL_CTRL_PHY_REQ;
1994 ble_ll_ctrl_phy_req_rsp_make(connsm, ctrdata);
1995 break;
1996 #endif
1997 default:
1998 BLE_LL_ASSERT(0);
1999 break;
2000 }
2001
2002 /* Set llid, length and opcode */
2003 dptr[0] = opcode;
2004 len = g_ble_ll_ctrl_pkt_lengths[opcode] + 1;
2005
2006 /* Add packet to transmit queue of connection */
2007 ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len);
2008 }
2009
2010 return om;
2011 }
2012
2013 /**
2014 * Called to determine if the pdu is a TERMINATE_IND
2015 *
2016 * @param hdr
2017 * @param opcode
2018 *
2019 * @return int
2020 */
2021 int
ble_ll_ctrl_is_terminate_ind(uint8_t hdr,uint8_t opcode)2022 ble_ll_ctrl_is_terminate_ind(uint8_t hdr, uint8_t opcode)
2023 {
2024 int rc;
2025
2026 rc = 0;
2027 if ((hdr & BLE_LL_DATA_HDR_LLID_MASK) == BLE_LL_LLID_CTRL) {
2028 if (opcode == BLE_LL_CTRL_TERMINATE_IND) {
2029 rc = 1;
2030 }
2031 }
2032 return rc;
2033 }
2034
2035 /**
2036 * Stops the LL control procedure indicated by 'ctrl_proc'.
2037 *
2038 * Context: Link Layer task
2039 *
2040 * @param connsm
2041 * @param ctrl_proc
2042 */
2043 void
ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm * connsm,int ctrl_proc)2044 ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc)
2045 {
2046 if (connsm->cur_ctrl_proc == ctrl_proc) {
2047 ble_npl_callout_stop(&connsm->ctrl_proc_rsp_timer);
2048 connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE;
2049 }
2050 CLR_PENDING_CTRL_PROC(connsm, ctrl_proc);
2051
2052 /* If there are others, start them */
2053 ble_ll_ctrl_chk_proc_start(connsm);
2054 }
2055
2056 /**
2057 * Called to start the terminate procedure.
2058 *
2059 * Context: Link Layer task.
2060 *
2061 * @param connsm
2062 */
2063 void
ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm * connsm)2064 ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm)
2065 {
2066 int ctrl_proc;
2067 uint32_t usecs;
2068 struct os_mbuf *om;
2069
2070 BLE_LL_ASSERT(connsm->disconnect_reason != 0);
2071
2072 ctrl_proc = BLE_LL_CTRL_PROC_TERMINATE;
2073 om = ble_ll_ctrl_proc_init(connsm, ctrl_proc);
2074 if (om) {
2075 CONN_F_TERMINATE_STARTED(connsm) = 1;
2076
2077 /* Set terminate "timeout" */
2078 usecs = connsm->supervision_tmo * BLE_HCI_CONN_SPVN_TMO_UNITS * 1000;
2079 connsm->terminate_timeout = os_cputime_get32() +
2080 os_cputime_usecs_to_ticks(usecs);
2081 }
2082 }
2083
2084 /**
2085 * Called to start a LL control procedure except for the terminate procedure. We
2086 * always set the control procedure pending bit even if the control procedure
2087 * has been initiated.
2088 *
2089 * Context: Link Layer task.
2090 *
2091 * @param connsm Pointer to connection state machine.
2092 */
2093 void
ble_ll_ctrl_proc_start(struct ble_ll_conn_sm * connsm,int ctrl_proc)2094 ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc)
2095 {
2096 struct os_mbuf *om;
2097
2098 BLE_LL_ASSERT(ctrl_proc != BLE_LL_CTRL_PROC_TERMINATE);
2099
2100 om = NULL;
2101 if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) {
2102 /* Initiate the control procedure. */
2103 om = ble_ll_ctrl_proc_init(connsm, ctrl_proc);
2104 if (om) {
2105 /* Set the current control procedure */
2106 connsm->cur_ctrl_proc = ctrl_proc;
2107
2108 /* Initialize the procedure response timeout */
2109 if (ctrl_proc != BLE_LL_CTRL_PROC_CHAN_MAP_UPD) {
2110 ble_ll_ctrl_start_rsp_timer(connsm);
2111 }
2112 }
2113 }
2114
2115 /* Set bitmask denoting control procedure is pending */
2116 connsm->pending_ctrl_procs |= (1 << ctrl_proc);
2117 }
2118
2119 /**
2120 * Called to determine if we need to start a LL control procedure for the given
2121 * connection.
2122 *
2123 * Context: Link Layer
2124 *
2125 * @param connsm Pointer to connection state machine.
2126 */
2127 void
ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm * connsm)2128 ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm)
2129 {
2130 int i;
2131
2132 /* XXX: TODO new rules! Cannot start certain control procedures if other
2133 * ones are peer initiated. We need to wait. Deal with this.
2134 */
2135
2136 /*
2137 * If we are terminating, dont start any new procedures but start
2138 * terminate if needed
2139 */
2140 if (connsm->disconnect_reason) {
2141 if (!CONN_F_TERMINATE_STARTED(connsm)) {
2142 /*
2143 * If the terminate procedure has not started it means we were not
2144 * able to start it right away (no control pdu was available).
2145 * Start it now. No need to start any other procedures.
2146 */
2147 ble_ll_ctrl_terminate_start(connsm);
2148 }
2149 return;
2150 }
2151
2152 /* If there is a running procedure or no pending, do nothing */
2153 if ((connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_IDLE) &&
2154 (connsm->pending_ctrl_procs != 0)) {
2155 /*
2156 * The specification says there is no priority to control procedures
2157 * so just start from the first one for now.
2158 */
2159 for (i = 0; i < BLE_LL_CTRL_PROC_NUM; ++i) {
2160 if (IS_PENDING_CTRL_PROC(connsm, i)) {
2161 /*
2162 * The version exchange is a special case. If we have already
2163 * received the information dont start it.
2164 */
2165 if ((i == BLE_LL_CTRL_PROC_VERSION_XCHG) &&
2166 (connsm->csmflags.cfbit.rxd_version_ind)) {
2167 ble_ll_hci_ev_rd_rem_ver(connsm, BLE_ERR_SUCCESS);
2168 CLR_PENDING_CTRL_PROC(connsm, i);
2169 } else {
2170 ble_ll_ctrl_proc_start(connsm, i);
2171 break;
2172 }
2173 }
2174 }
2175 }
2176 }
2177
2178 /**
2179 * Called when the Link Layer receives a LL control PDU.
2180 *
2181 * NOTE: this function uses the received PDU for the response in some cases. If
2182 * the received PDU is not used it needs to be freed here.
2183 *
2184 * XXX: may want to check, for both master and slave, whether the control
2185 * pdu should be received by that role. Might make for less code...
2186 * Context: Link Layer
2187 *
2188 * @param om
2189 * @param connsm
2190 */
2191 int
ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm * connsm,struct os_mbuf * om)2192 ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om)
2193 {
2194 uint32_t features;
2195 uint32_t feature;
2196 uint8_t len;
2197 uint8_t opcode;
2198 uint8_t rsp_opcode;
2199 uint8_t *dptr;
2200 uint8_t *rspbuf;
2201 uint8_t *rspdata;
2202 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
2203 int restart_encryption;
2204 #endif
2205 int rc = 0;
2206
2207 /* XXX: where do we validate length received and packet header length?
2208 * do this in LL task when received. Someplace!!! What I mean
2209 * is we should validate the over the air length with the mbuf length.
2210 Should the PHY do that???? */
2211
2212 /*
2213 * dptr points to om_data pointer. The first byte of om_data is the
2214 * first byte of the Data Channel PDU header. Get length from header and
2215 * opcode from LL control PDU.
2216 */
2217 dptr = om->om_data;
2218 len = dptr[1];
2219 opcode = dptr[2];
2220
2221 /*
2222 * rspbuf points to first byte of response. The response buffer does not
2223 * contain the Data Channel PDU. Thus, the first byte of rspbuf is the
2224 * LL control PDU payload (the opcode of the control PDU). rspdata
2225 * points to CtrData in the control PDU.
2226 */
2227 rspbuf = dptr;
2228 rspdata = rspbuf + 1;
2229
2230 /* Move data pointer to start of control data (2 byte PDU hdr + opcode) */
2231 dptr += (BLE_LL_PDU_HDR_LEN + 1);
2232
2233 /*
2234 * Subtract the opcode from the length. Note that if the length was zero,
2235 * which would be an error, we will fail the check against the length
2236 * of the control packet.
2237 */
2238 --len;
2239
2240 ble_ll_trace_u32x2(BLE_LL_TRACE_ID_CTRL_RX, opcode, len);
2241
2242 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
2243 restart_encryption = 0;
2244 #endif
2245
2246 /* If opcode comes from reserved value or CtrlData fields is invalid
2247 * we shall respond with LL_UNKNOWN_RSP
2248 */
2249 if ((opcode >= BLE_LL_CTRL_OPCODES) ||
2250 (len != g_ble_ll_ctrl_pkt_lengths[opcode])) {
2251 rc = -1;
2252 rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP;
2253 goto ll_ctrl_send_rsp;
2254 }
2255
2256 /* Check if the feature is supported. */
2257 switch (opcode) {
2258 case BLE_LL_CTRL_LENGTH_REQ:
2259 feature = BLE_LL_FEAT_DATA_LEN_EXT;
2260 break;
2261 case BLE_LL_CTRL_SLAVE_FEATURE_REQ:
2262 feature = BLE_LL_FEAT_SLAVE_INIT;
2263 break;
2264 case BLE_LL_CTRL_CONN_PARM_REQ:
2265 case BLE_LL_CTRL_CONN_PARM_RSP:
2266 feature = BLE_LL_FEAT_CONN_PARM_REQ;
2267 break;
2268 case BLE_LL_CTRL_ENC_REQ:
2269 case BLE_LL_CTRL_START_ENC_REQ:
2270 case BLE_LL_CTRL_PAUSE_ENC_REQ:
2271 feature = BLE_LL_FEAT_LE_ENCRYPTION;
2272 break;
2273 case BLE_LL_CTRL_PING_REQ:
2274 feature = BLE_LL_FEAT_LE_PING;
2275 break;
2276 case BLE_LL_CTRL_PHY_REQ:
2277 feature = BLE_LL_FEAT_LE_2M_PHY | BLE_LL_FEAT_LE_CODED_PHY;
2278 break;
2279 case BLE_LL_CTRL_MIN_USED_CHAN_IND:
2280 feature = BLE_LL_FEAT_MIN_USED_CHAN;
2281 break;
2282 default:
2283 feature = 0;
2284 break;
2285 }
2286
2287 if (feature) {
2288 features = ble_ll_read_supp_features();
2289 if ((features & feature) == 0) {
2290 if (opcode == BLE_LL_CTRL_ENC_REQ) {
2291 if (connsm->conn_features & BLE_LL_FEAT_EXTENDED_REJ) {
2292 rsp_opcode = BLE_LL_CTRL_REJECT_IND_EXT;
2293 rspbuf[1] = opcode;
2294 rspbuf[2] = BLE_ERR_UNSUPP_REM_FEATURE;
2295
2296 } else {
2297 rsp_opcode = BLE_LL_CTRL_REJECT_IND;
2298 rspbuf[1] = BLE_ERR_UNSUPP_REM_FEATURE;
2299 }
2300 } else {
2301 /* Construct unknown rsp pdu */
2302 rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP;
2303 }
2304 goto ll_ctrl_send_rsp;
2305 }
2306 }
2307
2308 /* Process opcode */
2309 rsp_opcode = BLE_ERR_MAX;
2310 switch (opcode) {
2311 case BLE_LL_CTRL_CONN_UPDATE_IND:
2312 rsp_opcode = ble_ll_ctrl_rx_conn_update(connsm, dptr);
2313 break;
2314 case BLE_LL_CTRL_CHANNEL_MAP_REQ:
2315 rsp_opcode = ble_ll_ctrl_rx_chanmap_req(connsm, dptr);
2316 break;
2317 case BLE_LL_CTRL_LENGTH_REQ:
2318 /* Extract parameters and check if valid */
2319 if (ble_ll_ctrl_len_proc(connsm, dptr)) {
2320 rc = -1;
2321 rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP;
2322 goto ll_ctrl_send_rsp;
2323 }
2324
2325 /*
2326 * If we have not started this procedure ourselves and it is
2327 * pending, no need to perform it.
2328 */
2329 if ((connsm->cur_ctrl_proc != BLE_LL_CTRL_PROC_DATA_LEN_UPD) &&
2330 IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD)) {
2331 CLR_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
2332 }
2333
2334 /* Send a response */
2335 rsp_opcode = BLE_LL_CTRL_LENGTH_RSP;
2336 ble_ll_ctrl_datalen_upd_make(connsm, rspbuf);
2337 break;
2338 case BLE_LL_CTRL_LENGTH_RSP:
2339 /* According to specification, process this only if we asked for it. */
2340 if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_DATA_LEN_UPD) {
2341 /*
2342 * Process the received data. If received data is invalid, we'll
2343 * reply with LL_UNKNOWN_RSP as per spec, but we still need to stop
2344 * control procedure to avoid timeout.
2345 */
2346 if (ble_ll_ctrl_len_proc(connsm, dptr)) {
2347 rc = -1;
2348 rsp_opcode = BLE_LL_CTRL_UNKNOWN_RSP;
2349 }
2350
2351 /* Stop the control procedure */
2352 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
2353 }
2354 break;
2355 case BLE_LL_CTRL_UNKNOWN_RSP:
2356 rsp_opcode = ble_ll_ctrl_proc_unk_rsp(connsm, dptr, rspdata);
2357 break;
2358 case BLE_LL_CTRL_FEATURE_REQ:
2359 rsp_opcode = ble_ll_ctrl_rx_feature_req(connsm, dptr, rspbuf, opcode);
2360 break;
2361 /* XXX: check to see if ctrl procedure was running? Do we care? */
2362 case BLE_LL_CTRL_FEATURE_RSP:
2363 connsm->conn_features = dptr[0];
2364 memcpy(connsm->remote_features, dptr + 1, 7);
2365 /* If this is the first time we received remote features, try to start DLE */
2366 if (!connsm->csmflags.cfbit.rxd_features) {
2367 ble_ll_ctrl_initiate_dle(connsm);
2368 connsm->csmflags.cfbit.rxd_features = 1;
2369 }
2370 /* Stop the control procedure */
2371 if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG)) {
2372 ble_ll_ctrl_proc_stop(connsm, BLE_LL_CTRL_PROC_FEATURE_XCHG);
2373 }
2374 /* Send event to host if pending features read */
2375 if (connsm->csmflags.cfbit.pending_hci_rd_features) {
2376 ble_ll_hci_ev_rd_rem_used_feat(connsm, BLE_ERR_SUCCESS);
2377 connsm->csmflags.cfbit.pending_hci_rd_features = 0;
2378 }
2379 break;
2380 case BLE_LL_CTRL_VERSION_IND:
2381 rsp_opcode = ble_ll_ctrl_rx_version_ind(connsm, dptr, rspdata);
2382 break;
2383 case BLE_LL_CTRL_SLAVE_FEATURE_REQ:
2384 rsp_opcode = ble_ll_ctrl_rx_feature_req(connsm, dptr, rspbuf, opcode);
2385 break;
2386 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
2387 case BLE_LL_CTRL_ENC_REQ:
2388 rsp_opcode = ble_ll_ctrl_rx_enc_req(connsm, dptr, rspdata);
2389 break;
2390 case BLE_LL_CTRL_ENC_RSP:
2391 ble_ll_ctrl_rx_enc_rsp(connsm, dptr);
2392 break;
2393 case BLE_LL_CTRL_START_ENC_REQ:
2394 rsp_opcode = ble_ll_ctrl_rx_start_enc_req(connsm);
2395 break;
2396 case BLE_LL_CTRL_START_ENC_RSP:
2397 rsp_opcode = ble_ll_ctrl_rx_start_enc_rsp(connsm);
2398 break;
2399 case BLE_LL_CTRL_PAUSE_ENC_REQ:
2400 rsp_opcode = ble_ll_ctrl_rx_pause_enc_req(connsm);
2401 break;
2402 case BLE_LL_CTRL_PAUSE_ENC_RSP:
2403 rsp_opcode = ble_ll_ctrl_rx_pause_enc_rsp(connsm);
2404 if (rsp_opcode == BLE_LL_CTRL_PAUSE_ENC_RSP) {
2405 restart_encryption = 1;
2406 }
2407 break;
2408 #endif
2409 case BLE_LL_CTRL_PING_REQ:
2410 rsp_opcode = BLE_LL_CTRL_PING_RSP;
2411 break;
2412 case BLE_LL_CTRL_PING_RSP:
2413 ble_ll_ctrl_rx_ping_rsp(connsm);
2414 break;
2415 case BLE_LL_CTRL_CONN_PARM_REQ:
2416 rsp_opcode = ble_ll_ctrl_rx_conn_param_req(connsm, dptr, rspbuf);
2417 break;
2418 case BLE_LL_CTRL_CONN_PARM_RSP:
2419 rsp_opcode = ble_ll_ctrl_rx_conn_param_rsp(connsm, dptr, rspbuf);
2420 break;
2421 /* Fall-through intentional... */
2422 case BLE_LL_CTRL_REJECT_IND:
2423 case BLE_LL_CTRL_REJECT_IND_EXT:
2424 /* Sometimes reject triggers sending other LL CTRL msg */
2425 rsp_opcode = ble_ll_ctrl_rx_reject_ind(connsm, dptr, opcode, rspdata);
2426 break;
2427 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
2428 case BLE_LL_CTRL_PHY_REQ:
2429 rsp_opcode = ble_ll_ctrl_rx_phy_req(connsm, dptr, rspdata);
2430 break;
2431 case BLE_LL_CTRL_PHY_RSP:
2432 rsp_opcode = ble_ll_ctrl_rx_phy_rsp(connsm, dptr, rspdata);
2433 break;
2434 case BLE_LL_CTRL_PHY_UPDATE_IND:
2435 rsp_opcode = ble_ll_ctrl_rx_phy_update_ind(connsm, dptr);
2436 break;
2437 #endif
2438 default:
2439 /* Nothing to do here */
2440 break;
2441 }
2442
2443 /* Free mbuf or send response */
2444 ll_ctrl_send_rsp:
2445 if (rsp_opcode == BLE_ERR_MAX) {
2446 os_mbuf_free_chain(om);
2447 } else {
2448 /*
2449 * Write the response opcode into the buffer. If this is an unknown
2450 * response, put opcode of unknown pdu into buffer.
2451 */
2452 rspbuf[0] = rsp_opcode;
2453 if (rsp_opcode == BLE_LL_CTRL_UNKNOWN_RSP) {
2454 rspbuf[1] = opcode;
2455 }
2456 len = g_ble_ll_ctrl_pkt_lengths[rsp_opcode] + 1;
2457 ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len);
2458 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
2459 if (restart_encryption) {
2460 /* XXX: what happens if this fails? Meaning we cant allocate
2461 mbuf? */
2462 ble_ll_ctrl_proc_init(connsm, BLE_LL_CTRL_PROC_ENCRYPT);
2463 }
2464 #endif
2465 }
2466 return rc;
2467 }
2468
2469 /**
2470 * Called to create and send a REJECT_IND_EXT control PDU or a REJECT_IND
2471 *
2472 * @param connsm
2473 * @param rej_opcode
2474 * @param err
2475 *
2476 * @return int
2477 */
2478 int
ble_ll_ctrl_reject_ind_send(struct ble_ll_conn_sm * connsm,uint8_t rej_opcode,uint8_t err)2479 ble_ll_ctrl_reject_ind_send(struct ble_ll_conn_sm *connsm, uint8_t rej_opcode,
2480 uint8_t err)
2481 {
2482 int rc;
2483 uint8_t len;
2484 uint8_t opcode;
2485 uint8_t *rspbuf;
2486 struct os_mbuf *om;
2487
2488 om = os_msys_get_pkthdr(BLE_LL_CTRL_MAX_PDU_LEN,
2489 sizeof(struct ble_mbuf_hdr));
2490 if (om) {
2491 rspbuf = om->om_data;
2492 opcode = BLE_LL_CTRL_REJECT_IND_EXT;
2493 if (rej_opcode == BLE_LL_CTRL_ENC_REQ) {
2494 if ((connsm->conn_features & BLE_LL_FEAT_EXTENDED_REJ) == 0) {
2495 opcode = BLE_LL_CTRL_REJECT_IND;
2496 }
2497 }
2498 rspbuf[0] = opcode;
2499 if (opcode == BLE_LL_CTRL_REJECT_IND) {
2500 rspbuf[1] = err;
2501 len = BLE_LL_CTRL_REJ_IND_LEN + 1;
2502 } else {
2503 rspbuf[1] = rej_opcode;
2504 rspbuf[2] = err;
2505 len = BLE_LL_CTRL_REJECT_IND_EXT_LEN + 1;
2506 }
2507 ble_ll_conn_enqueue_pkt(connsm, om, BLE_LL_LLID_CTRL, len);
2508 rc = 0;
2509 } else {
2510 rc = 1;
2511 }
2512 return rc;
2513 }
2514
2515 /**
2516 * Called when a Link Layer Control pdu has been transmitted successfully.
2517 * This is called when we have a received a PDU during the ISR.
2518 *
2519 * Context: ISR
2520 *
2521 * @param txpdu
2522 *
2523 * @return int
2524 */
2525 int
ble_ll_ctrl_tx_done(struct os_mbuf * txpdu,struct ble_ll_conn_sm * connsm)2526 ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm)
2527 {
2528 int rc;
2529 uint8_t opcode;
2530
2531 rc = 0;
2532 opcode = txpdu->om_data[0];
2533 switch (opcode) {
2534 case BLE_LL_CTRL_TERMINATE_IND:
2535 connsm->csmflags.cfbit.terminate_ind_txd = 1;
2536 rc = -1;
2537 break;
2538 case BLE_LL_CTRL_REJECT_IND_EXT:
2539 if (connsm->cur_ctrl_proc == BLE_LL_CTRL_PROC_CONN_PARAM_REQ) {
2540 /* If rejecting opcode is BLE_LL_CTRL_PROC_CONN_PARAM_REQ and
2541 * reason is LMP collision that means we are master on the link and
2542 * peer wanted to start procedure which we already started.
2543 * Let's wait for response and do not close procedure. */
2544 if (txpdu->om_data[1] == BLE_LL_CTRL_CONN_PARM_REQ &&
2545 txpdu->om_data[2] != BLE_ERR_LMP_COLLISION) {
2546 connsm->reject_reason = txpdu->om_data[2];
2547 connsm->csmflags.cfbit.host_expects_upd_event = 1;
2548 }
2549 }
2550 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
2551 if (connsm->enc_data.enc_state > CONN_ENC_S_ENCRYPTED) {
2552 connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED;
2553 }
2554 #endif
2555 break;
2556 case BLE_LL_CTRL_REJECT_IND:
2557 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
2558 connsm->enc_data.enc_state = CONN_ENC_S_UNENCRYPTED;
2559 #endif
2560 break;
2561 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
2562 case BLE_LL_CTRL_PAUSE_ENC_REQ:
2563 /* note: fall-through intentional */
2564 case BLE_LL_CTRL_ENC_REQ:
2565 connsm->enc_data.enc_state = CONN_ENC_S_ENC_RSP_WAIT;
2566 break;
2567 case BLE_LL_CTRL_ENC_RSP:
2568 connsm->enc_data.enc_state = CONN_ENC_S_LTK_REQ_WAIT;
2569 connsm->csmflags.cfbit.send_ltk_req = 1;
2570 break;
2571 case BLE_LL_CTRL_START_ENC_RSP:
2572 if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
2573 connsm->enc_data.enc_state = CONN_ENC_S_ENCRYPTED;
2574 if (CONN_F_LE_PING_SUPP(connsm)) {
2575 ble_ll_conn_auth_pyld_timer_start(connsm);
2576 }
2577 }
2578 break;
2579 case BLE_LL_CTRL_PAUSE_ENC_RSP:
2580 if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
2581 connsm->enc_data.enc_state = CONN_ENC_S_PAUSE_ENC_RSP_WAIT;
2582 }
2583 break;
2584 #endif
2585 #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
2586 case BLE_LL_CTRL_PHY_REQ:
2587 if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
2588 if (connsm->phy_data.req_pref_tx_phys_mask & BLE_PHY_MASK_1M) {
2589 connsm->phy_tx_transition = BLE_PHY_1M;
2590 } else if (connsm->phy_data.req_pref_tx_phys_mask & BLE_PHY_MASK_2M) {
2591 connsm->phy_tx_transition = BLE_PHY_2M;
2592 } else if (connsm->phy_data.req_pref_tx_phys_mask & BLE_PHY_MASK_CODED) {
2593 connsm->phy_tx_transition = BLE_PHY_CODED;
2594 }
2595 }
2596 break;
2597 #endif
2598 default:
2599 break;
2600 }
2601
2602 os_mbuf_free_chain(txpdu);
2603 return rc;
2604 }
2605