xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/controller/src/ble_ll_ctrl.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 #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