xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/controller/src/ble_ll_hci.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1*042d53a7SEvalZero /*
2*042d53a7SEvalZero  * Licensed to the Apache Software Foundation (ASF) under one
3*042d53a7SEvalZero  * or more contributor license agreements.  See the NOTICE file
4*042d53a7SEvalZero  * distributed with this work for additional information
5*042d53a7SEvalZero  * regarding copyright ownership.  The ASF licenses this file
6*042d53a7SEvalZero  * to you under the Apache License, Version 2.0 (the
7*042d53a7SEvalZero  * "License"); you may not use this file except in compliance
8*042d53a7SEvalZero  * with the License.  You may obtain a copy of the License at
9*042d53a7SEvalZero  *
10*042d53a7SEvalZero  *  http://www.apache.org/licenses/LICENSE-2.0
11*042d53a7SEvalZero  *
12*042d53a7SEvalZero  * Unless required by applicable law or agreed to in writing,
13*042d53a7SEvalZero  * software distributed under the License is distributed on an
14*042d53a7SEvalZero  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*042d53a7SEvalZero  * KIND, either express or implied.  See the License for the
16*042d53a7SEvalZero  * specific language governing permissions and limitations
17*042d53a7SEvalZero  * under the License.
18*042d53a7SEvalZero  */
19*042d53a7SEvalZero #include <stdint.h>
20*042d53a7SEvalZero #include <assert.h>
21*042d53a7SEvalZero #include <string.h>
22*042d53a7SEvalZero #include "syscfg/syscfg.h"
23*042d53a7SEvalZero #include "os/os.h"
24*042d53a7SEvalZero #include "nimble/ble.h"
25*042d53a7SEvalZero #include "nimble/nimble_opt.h"
26*042d53a7SEvalZero #include "nimble/hci_common.h"
27*042d53a7SEvalZero #include "nimble/ble_hci_trans.h"
28*042d53a7SEvalZero #include "controller/ble_hw.h"
29*042d53a7SEvalZero #include "controller/ble_ll_adv.h"
30*042d53a7SEvalZero #include "controller/ble_ll_scan.h"
31*042d53a7SEvalZero #include "controller/ble_ll.h"
32*042d53a7SEvalZero #include "controller/ble_ll_hci.h"
33*042d53a7SEvalZero #include "controller/ble_ll_whitelist.h"
34*042d53a7SEvalZero #include "controller/ble_ll_resolv.h"
35*042d53a7SEvalZero #include "ble_ll_conn_priv.h"
36*042d53a7SEvalZero 
37*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
38*042d53a7SEvalZero #include "ble_ll_dtm_priv.h"
39*042d53a7SEvalZero #endif
40*042d53a7SEvalZero 
41*042d53a7SEvalZero static void ble_ll_hci_cmd_proc(struct ble_npl_event *ev);
42*042d53a7SEvalZero 
43*042d53a7SEvalZero /* OS event to enqueue command */
44*042d53a7SEvalZero static struct ble_npl_event g_ble_ll_hci_cmd_ev;
45*042d53a7SEvalZero 
46*042d53a7SEvalZero /* LE event mask */
47*042d53a7SEvalZero static uint8_t g_ble_ll_hci_le_event_mask[BLE_HCI_SET_LE_EVENT_MASK_LEN];
48*042d53a7SEvalZero static uint8_t g_ble_ll_hci_event_mask[BLE_HCI_SET_EVENT_MASK_LEN];
49*042d53a7SEvalZero static uint8_t g_ble_ll_hci_event_mask2[BLE_HCI_SET_EVENT_MASK_LEN];
50*042d53a7SEvalZero 
51*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
52*042d53a7SEvalZero static enum {
53*042d53a7SEvalZero     ADV_MODE_ANY,
54*042d53a7SEvalZero     ADV_MODE_LEGACY,
55*042d53a7SEvalZero     ADV_MODE_EXT,
56*042d53a7SEvalZero } hci_adv_mode;
57*042d53a7SEvalZero 
ble_ll_hci_adv_mode_ext(void)58*042d53a7SEvalZero bool ble_ll_hci_adv_mode_ext(void)
59*042d53a7SEvalZero {
60*042d53a7SEvalZero     return hci_adv_mode == ADV_MODE_EXT;
61*042d53a7SEvalZero }
62*042d53a7SEvalZero #else
63*042d53a7SEvalZero bool
ble_ll_hci_adv_mode_ext(void)64*042d53a7SEvalZero ble_ll_hci_adv_mode_ext(void)
65*042d53a7SEvalZero {
66*042d53a7SEvalZero     return false;
67*042d53a7SEvalZero }
68*042d53a7SEvalZero #endif
69*042d53a7SEvalZero 
70*042d53a7SEvalZero /**
71*042d53a7SEvalZero  * ll hci get num cmd pkts
72*042d53a7SEvalZero  *
73*042d53a7SEvalZero  * Returns the number of command packets that the host is allowed to send
74*042d53a7SEvalZero  * to the controller.
75*042d53a7SEvalZero  *
76*042d53a7SEvalZero  * @return uint8_t
77*042d53a7SEvalZero  */
78*042d53a7SEvalZero static uint8_t
ble_ll_hci_get_num_cmd_pkts(void)79*042d53a7SEvalZero ble_ll_hci_get_num_cmd_pkts(void)
80*042d53a7SEvalZero {
81*042d53a7SEvalZero     return BLE_LL_CFG_NUM_HCI_CMD_PKTS;
82*042d53a7SEvalZero }
83*042d53a7SEvalZero 
84*042d53a7SEvalZero /**
85*042d53a7SEvalZero  * Send an event to the host.
86*042d53a7SEvalZero  *
87*042d53a7SEvalZero  * @param evbuf Pointer to event buffer to send
88*042d53a7SEvalZero  *
89*042d53a7SEvalZero  * @return int 0: success; -1 otherwise.
90*042d53a7SEvalZero  */
91*042d53a7SEvalZero int
ble_ll_hci_event_send(uint8_t * evbuf)92*042d53a7SEvalZero ble_ll_hci_event_send(uint8_t *evbuf)
93*042d53a7SEvalZero {
94*042d53a7SEvalZero     int rc;
95*042d53a7SEvalZero 
96*042d53a7SEvalZero     BLE_LL_ASSERT(BLE_HCI_EVENT_HDR_LEN + evbuf[1] <= BLE_LL_MAX_EVT_LEN);
97*042d53a7SEvalZero 
98*042d53a7SEvalZero     /* Count number of events sent */
99*042d53a7SEvalZero     STATS_INC(ble_ll_stats, hci_events_sent);
100*042d53a7SEvalZero 
101*042d53a7SEvalZero     /* Send the event to the host */
102*042d53a7SEvalZero     rc = ble_hci_trans_ll_evt_tx(evbuf);
103*042d53a7SEvalZero 
104*042d53a7SEvalZero     return rc;
105*042d53a7SEvalZero }
106*042d53a7SEvalZero 
107*042d53a7SEvalZero /**
108*042d53a7SEvalZero  * Created and sends a command complete event with the no-op opcode to the
109*042d53a7SEvalZero  * host.
110*042d53a7SEvalZero  *
111*042d53a7SEvalZero  * @return int 0: ok, ble error code otherwise.
112*042d53a7SEvalZero  */
113*042d53a7SEvalZero int
ble_ll_hci_send_noop(void)114*042d53a7SEvalZero ble_ll_hci_send_noop(void)
115*042d53a7SEvalZero {
116*042d53a7SEvalZero     int rc;
117*042d53a7SEvalZero     uint8_t *evbuf;
118*042d53a7SEvalZero     uint16_t opcode;
119*042d53a7SEvalZero 
120*042d53a7SEvalZero     evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
121*042d53a7SEvalZero     if (evbuf) {
122*042d53a7SEvalZero         /* Create a command complete event with a NO-OP opcode */
123*042d53a7SEvalZero         opcode = 0;
124*042d53a7SEvalZero         evbuf[0] = BLE_HCI_EVCODE_COMMAND_COMPLETE;
125*042d53a7SEvalZero         evbuf[1] = 3;
126*042d53a7SEvalZero         evbuf[2] = ble_ll_hci_get_num_cmd_pkts();
127*042d53a7SEvalZero         put_le16(evbuf + 3, opcode);
128*042d53a7SEvalZero         ble_ll_hci_event_send(evbuf);
129*042d53a7SEvalZero         rc = BLE_ERR_SUCCESS;
130*042d53a7SEvalZero     } else {
131*042d53a7SEvalZero         rc = BLE_ERR_MEM_CAPACITY;
132*042d53a7SEvalZero     }
133*042d53a7SEvalZero 
134*042d53a7SEvalZero     return rc;
135*042d53a7SEvalZero }
136*042d53a7SEvalZero 
137*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
138*042d53a7SEvalZero /**
139*042d53a7SEvalZero  * LE encrypt command
140*042d53a7SEvalZero  *
141*042d53a7SEvalZero  * @param cmdbuf
142*042d53a7SEvalZero  * @param rspbuf
143*042d53a7SEvalZero  * @param rsplen
144*042d53a7SEvalZero  *
145*042d53a7SEvalZero  * @return int
146*042d53a7SEvalZero  */
147*042d53a7SEvalZero static int
ble_ll_hci_le_encrypt(uint8_t * cmdbuf,uint8_t * rspbuf,uint8_t * rsplen)148*042d53a7SEvalZero ble_ll_hci_le_encrypt(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
149*042d53a7SEvalZero {
150*042d53a7SEvalZero     int rc;
151*042d53a7SEvalZero     struct ble_encryption_block ecb;
152*042d53a7SEvalZero 
153*042d53a7SEvalZero     /* Call the link layer to encrypt the data */
154*042d53a7SEvalZero     swap_buf(ecb.key, cmdbuf, BLE_ENC_BLOCK_SIZE);
155*042d53a7SEvalZero     swap_buf(ecb.plain_text, cmdbuf + BLE_ENC_BLOCK_SIZE, BLE_ENC_BLOCK_SIZE);
156*042d53a7SEvalZero     rc = ble_hw_encrypt_block(&ecb);
157*042d53a7SEvalZero     if (!rc) {
158*042d53a7SEvalZero         swap_buf(rspbuf, ecb.cipher_text, BLE_ENC_BLOCK_SIZE);
159*042d53a7SEvalZero         *rsplen = BLE_ENC_BLOCK_SIZE;
160*042d53a7SEvalZero         rc = BLE_ERR_SUCCESS;
161*042d53a7SEvalZero     } else {
162*042d53a7SEvalZero         *rsplen = 0;
163*042d53a7SEvalZero         rc = BLE_ERR_CTLR_BUSY;
164*042d53a7SEvalZero     }
165*042d53a7SEvalZero     return rc;
166*042d53a7SEvalZero }
167*042d53a7SEvalZero #endif
168*042d53a7SEvalZero 
169*042d53a7SEvalZero /**
170*042d53a7SEvalZero  * LE rand command
171*042d53a7SEvalZero  *
172*042d53a7SEvalZero  * @param cmdbuf
173*042d53a7SEvalZero  * @param rspbuf
174*042d53a7SEvalZero  * @param rsplen
175*042d53a7SEvalZero  *
176*042d53a7SEvalZero  * @return int
177*042d53a7SEvalZero  */
178*042d53a7SEvalZero static int
ble_ll_hci_le_rand(uint8_t * rspbuf,uint8_t * rsplen)179*042d53a7SEvalZero ble_ll_hci_le_rand(uint8_t *rspbuf, uint8_t *rsplen)
180*042d53a7SEvalZero {
181*042d53a7SEvalZero     int rc;
182*042d53a7SEvalZero 
183*042d53a7SEvalZero     rc = ble_ll_rand_data_get(rspbuf, BLE_HCI_LE_RAND_LEN);
184*042d53a7SEvalZero     *rsplen = BLE_HCI_LE_RAND_LEN;
185*042d53a7SEvalZero     return rc;
186*042d53a7SEvalZero }
187*042d53a7SEvalZero 
188*042d53a7SEvalZero /**
189*042d53a7SEvalZero  * Read local version
190*042d53a7SEvalZero  *
191*042d53a7SEvalZero  * @param rspbuf
192*042d53a7SEvalZero  * @param rsplen
193*042d53a7SEvalZero  *
194*042d53a7SEvalZero  * @return int
195*042d53a7SEvalZero  */
196*042d53a7SEvalZero static int
ble_ll_hci_rd_local_version(uint8_t * rspbuf,uint8_t * rsplen)197*042d53a7SEvalZero ble_ll_hci_rd_local_version(uint8_t *rspbuf, uint8_t *rsplen)
198*042d53a7SEvalZero {
199*042d53a7SEvalZero     uint16_t hci_rev;
200*042d53a7SEvalZero     uint16_t lmp_subver;
201*042d53a7SEvalZero     uint16_t mfrg;
202*042d53a7SEvalZero 
203*042d53a7SEvalZero     hci_rev = 0;
204*042d53a7SEvalZero     lmp_subver = 0;
205*042d53a7SEvalZero     mfrg = MYNEWT_VAL(BLE_LL_MFRG_ID);
206*042d53a7SEvalZero 
207*042d53a7SEvalZero     /* Place the data packet length and number of packets in the buffer */
208*042d53a7SEvalZero     rspbuf[0] = BLE_HCI_VER_BCS_5_0;
209*042d53a7SEvalZero     put_le16(rspbuf + 1, hci_rev);
210*042d53a7SEvalZero     rspbuf[3] = BLE_LMP_VER_BCS_5_0;
211*042d53a7SEvalZero     put_le16(rspbuf + 4, mfrg);
212*042d53a7SEvalZero     put_le16(rspbuf + 6, lmp_subver);
213*042d53a7SEvalZero     *rsplen = BLE_HCI_RD_LOC_VER_INFO_RSPLEN;
214*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
215*042d53a7SEvalZero }
216*042d53a7SEvalZero 
217*042d53a7SEvalZero /**
218*042d53a7SEvalZero  * Read local supported features
219*042d53a7SEvalZero  *
220*042d53a7SEvalZero  * @param rspbuf
221*042d53a7SEvalZero  * @param rsplen
222*042d53a7SEvalZero  *
223*042d53a7SEvalZero  * @return int
224*042d53a7SEvalZero  */
225*042d53a7SEvalZero static int
ble_ll_hci_rd_local_supp_feat(uint8_t * rspbuf,uint8_t * rsplen)226*042d53a7SEvalZero ble_ll_hci_rd_local_supp_feat(uint8_t *rspbuf, uint8_t *rsplen)
227*042d53a7SEvalZero {
228*042d53a7SEvalZero     /*
229*042d53a7SEvalZero      * The only two bits we set here currently are:
230*042d53a7SEvalZero      *      BR/EDR not supported        (bit 5)
231*042d53a7SEvalZero      *      LE supported (controller)   (bit 6)
232*042d53a7SEvalZero      */
233*042d53a7SEvalZero     memset(rspbuf, 0, BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN);
234*042d53a7SEvalZero     rspbuf[4] = 0x60;
235*042d53a7SEvalZero     *rsplen = BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN;
236*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
237*042d53a7SEvalZero }
238*042d53a7SEvalZero 
239*042d53a7SEvalZero /**
240*042d53a7SEvalZero  * Read local supported commands
241*042d53a7SEvalZero  *
242*042d53a7SEvalZero  * @param rspbuf
243*042d53a7SEvalZero  * @param rsplen
244*042d53a7SEvalZero  *
245*042d53a7SEvalZero  * @return int
246*042d53a7SEvalZero  */
247*042d53a7SEvalZero static int
ble_ll_hci_rd_local_supp_cmd(uint8_t * rspbuf,uint8_t * rsplen)248*042d53a7SEvalZero ble_ll_hci_rd_local_supp_cmd(uint8_t *rspbuf, uint8_t *rsplen)
249*042d53a7SEvalZero {
250*042d53a7SEvalZero     memset(rspbuf, 0, BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN);
251*042d53a7SEvalZero     memcpy(rspbuf, g_ble_ll_supp_cmds, sizeof(g_ble_ll_supp_cmds));
252*042d53a7SEvalZero     *rsplen = BLE_HCI_RD_LOC_SUPP_CMD_RSPLEN;
253*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
254*042d53a7SEvalZero }
255*042d53a7SEvalZero 
256*042d53a7SEvalZero /**
257*042d53a7SEvalZero  * Called to read the public device address of the device
258*042d53a7SEvalZero  *
259*042d53a7SEvalZero  *
260*042d53a7SEvalZero  * @param rspbuf
261*042d53a7SEvalZero  * @param rsplen
262*042d53a7SEvalZero  *
263*042d53a7SEvalZero  * @return int
264*042d53a7SEvalZero  */
265*042d53a7SEvalZero static int
ble_ll_hci_rd_bd_addr(uint8_t * rspbuf,uint8_t * rsplen)266*042d53a7SEvalZero ble_ll_hci_rd_bd_addr(uint8_t *rspbuf, uint8_t *rsplen)
267*042d53a7SEvalZero {
268*042d53a7SEvalZero     /*
269*042d53a7SEvalZero      * XXX: for now, assume we always have a public device address. If we
270*042d53a7SEvalZero      * dont, we should set this to zero
271*042d53a7SEvalZero      */
272*042d53a7SEvalZero     memcpy(rspbuf, g_dev_addr, BLE_DEV_ADDR_LEN);
273*042d53a7SEvalZero     *rsplen = BLE_DEV_ADDR_LEN;
274*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
275*042d53a7SEvalZero }
276*042d53a7SEvalZero 
277*042d53a7SEvalZero /**
278*042d53a7SEvalZero  * ll hci set le event mask
279*042d53a7SEvalZero  *
280*042d53a7SEvalZero  * Called when the LL controller receives a set LE event mask command.
281*042d53a7SEvalZero  *
282*042d53a7SEvalZero  * Context: Link Layer task (HCI command parser)
283*042d53a7SEvalZero  *
284*042d53a7SEvalZero  * @param cmdbuf Pointer to command buf.
285*042d53a7SEvalZero  *
286*042d53a7SEvalZero  * @return int BLE_ERR_SUCCESS. Does not return any errors.
287*042d53a7SEvalZero  */
288*042d53a7SEvalZero static int
ble_ll_hci_set_le_event_mask(uint8_t * cmdbuf)289*042d53a7SEvalZero ble_ll_hci_set_le_event_mask(uint8_t *cmdbuf)
290*042d53a7SEvalZero {
291*042d53a7SEvalZero     /* Copy the data into the event mask */
292*042d53a7SEvalZero     memcpy(g_ble_ll_hci_le_event_mask, cmdbuf, BLE_HCI_SET_LE_EVENT_MASK_LEN);
293*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
294*042d53a7SEvalZero }
295*042d53a7SEvalZero 
296*042d53a7SEvalZero /**
297*042d53a7SEvalZero  * HCI read buffer size command. Returns the ACL data packet length and
298*042d53a7SEvalZero  * num data packets.
299*042d53a7SEvalZero  *
300*042d53a7SEvalZero  * @param rspbuf Pointer to response buffer
301*042d53a7SEvalZero  * @param rsplen Length of response buffer
302*042d53a7SEvalZero  *
303*042d53a7SEvalZero  * @return int BLE error code
304*042d53a7SEvalZero  */
305*042d53a7SEvalZero static int
ble_ll_hci_le_read_bufsize(uint8_t * rspbuf,uint8_t * rsplen)306*042d53a7SEvalZero ble_ll_hci_le_read_bufsize(uint8_t *rspbuf, uint8_t *rsplen)
307*042d53a7SEvalZero {
308*042d53a7SEvalZero     /* Place the data packet length and number of packets in the buffer */
309*042d53a7SEvalZero     put_le16(rspbuf, g_ble_ll_data.ll_acl_pkt_size);
310*042d53a7SEvalZero     rspbuf[2] = g_ble_ll_data.ll_num_acl_pkts;
311*042d53a7SEvalZero     *rsplen = BLE_HCI_RD_BUF_SIZE_RSPLEN;
312*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
313*042d53a7SEvalZero }
314*042d53a7SEvalZero 
315*042d53a7SEvalZero #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
316*042d53a7SEvalZero /**
317*042d53a7SEvalZero  * Checks the preferred phy masks for validity and places the preferred masks
318*042d53a7SEvalZero  * in the input phy masks
319*042d53a7SEvalZero  *
320*042d53a7SEvalZero  * @param cmdbuf Pointer to command buffer where phy masks are located
321*042d53a7SEvalZero  * @param txphy Pointer to output tx phy mask
322*042d53a7SEvalZero  * @param rxphy Pointer to output rx phy mask
323*042d53a7SEvalZero  *
324*042d53a7SEvalZero  * @return int BLE_ERR_SUCCESS or BLE_ERR_INV_HCI_CMD_PARMS or BLE_ERR_UNSUPPORTED
325*042d53a7SEvalZero  */
326*042d53a7SEvalZero int
ble_ll_hci_chk_phy_masks(uint8_t * cmdbuf,uint8_t * txphy,uint8_t * rxphy)327*042d53a7SEvalZero ble_ll_hci_chk_phy_masks(uint8_t *cmdbuf, uint8_t *txphy, uint8_t *rxphy)
328*042d53a7SEvalZero {
329*042d53a7SEvalZero     uint8_t all_phys;
330*042d53a7SEvalZero     uint8_t rx_phys;
331*042d53a7SEvalZero     uint8_t tx_phys;
332*042d53a7SEvalZero 
333*042d53a7SEvalZero     /* Check for RFU */
334*042d53a7SEvalZero     if ((cmdbuf[1] & ~BLE_HCI_LE_PHY_PREF_MASK_ALL) ||
335*042d53a7SEvalZero                     (cmdbuf[2] & ~BLE_HCI_LE_PHY_PREF_MASK_ALL)) {
336*042d53a7SEvalZero         return BLE_ERR_UNSUPPORTED;
337*042d53a7SEvalZero     }
338*042d53a7SEvalZero 
339*042d53a7SEvalZero     /* Check for valid values */
340*042d53a7SEvalZero     all_phys = cmdbuf[0];
341*042d53a7SEvalZero     tx_phys = cmdbuf[1] & BLE_HCI_LE_PHY_PREF_MASK_ALL;
342*042d53a7SEvalZero     rx_phys = cmdbuf[2] & BLE_HCI_LE_PHY_PREF_MASK_ALL;
343*042d53a7SEvalZero 
344*042d53a7SEvalZero     if ((!(all_phys & BLE_HCI_LE_PHY_NO_TX_PREF_MASK) && (tx_phys == 0)) ||
345*042d53a7SEvalZero         (!(all_phys & BLE_HCI_LE_PHY_NO_RX_PREF_MASK) && (rx_phys == 0))) {
346*042d53a7SEvalZero         return BLE_ERR_INV_HCI_CMD_PARMS;
347*042d53a7SEvalZero     }
348*042d53a7SEvalZero 
349*042d53a7SEvalZero     /* If phy not supported, return error */
350*042d53a7SEvalZero #if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
351*042d53a7SEvalZero     if((tx_phys & BLE_HCI_LE_PHY_2M_PREF_MASK) ||
352*042d53a7SEvalZero                     (rx_phys & BLE_HCI_LE_PHY_2M_PREF_MASK)) {
353*042d53a7SEvalZero         return BLE_ERR_UNSUPPORTED;
354*042d53a7SEvalZero     }
355*042d53a7SEvalZero #endif
356*042d53a7SEvalZero #if !MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
357*042d53a7SEvalZero     if ((tx_phys & BLE_HCI_LE_PHY_CODED_PREF_MASK) ||
358*042d53a7SEvalZero                     (rx_phys & BLE_HCI_LE_PHY_CODED_PREF_MASK)) {
359*042d53a7SEvalZero         return BLE_ERR_UNSUPPORTED;
360*042d53a7SEvalZero     }
361*042d53a7SEvalZero #endif
362*042d53a7SEvalZero     /* Set the default PHY preferences */
363*042d53a7SEvalZero     if (all_phys & BLE_HCI_LE_PHY_NO_TX_PREF_MASK) {
364*042d53a7SEvalZero         tx_phys = BLE_HCI_LE_PHY_PREF_MASK_ALL;
365*042d53a7SEvalZero     }
366*042d53a7SEvalZero     *txphy = tx_phys;
367*042d53a7SEvalZero 
368*042d53a7SEvalZero     if (all_phys & BLE_HCI_LE_PHY_NO_RX_PREF_MASK) {
369*042d53a7SEvalZero         rx_phys = BLE_HCI_LE_PHY_PREF_MASK_ALL;
370*042d53a7SEvalZero     }
371*042d53a7SEvalZero     *rxphy = rx_phys;
372*042d53a7SEvalZero 
373*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
374*042d53a7SEvalZero }
375*042d53a7SEvalZero 
376*042d53a7SEvalZero /**
377*042d53a7SEvalZero  * Set PHY preferences for connection
378*042d53a7SEvalZero  *
379*042d53a7SEvalZero  * @param cmdbuf
380*042d53a7SEvalZero  *
381*042d53a7SEvalZero  * @return int
382*042d53a7SEvalZero  */
383*042d53a7SEvalZero static int
ble_ll_hci_le_set_def_phy(uint8_t * cmdbuf)384*042d53a7SEvalZero ble_ll_hci_le_set_def_phy(uint8_t *cmdbuf)
385*042d53a7SEvalZero {
386*042d53a7SEvalZero     int rc;
387*042d53a7SEvalZero 
388*042d53a7SEvalZero     rc = ble_ll_hci_chk_phy_masks(cmdbuf, &g_ble_ll_data.ll_pref_tx_phys,
389*042d53a7SEvalZero                                   &g_ble_ll_data.ll_pref_rx_phys);
390*042d53a7SEvalZero     return rc;
391*042d53a7SEvalZero }
392*042d53a7SEvalZero #endif
393*042d53a7SEvalZero 
394*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) == 1)
395*042d53a7SEvalZero /**
396*042d53a7SEvalZero  * HCI write suggested default data length command.
397*042d53a7SEvalZero  *
398*042d53a7SEvalZero  * This command is used by the host to change the initial max tx octets/time
399*042d53a7SEvalZero  * for all connections. Note that if the controller does not support the
400*042d53a7SEvalZero  * requested times no error is returned; the controller simply ignores the
401*042d53a7SEvalZero  * request (but remembers what the host requested for the read suggested
402*042d53a7SEvalZero  * default data length command). The spec allows for the controller to
403*042d53a7SEvalZero  * disregard the host.
404*042d53a7SEvalZero  *
405*042d53a7SEvalZero  * @param rspbuf Pointer to response buffer
406*042d53a7SEvalZero  * @param rsplen Length of response buffer
407*042d53a7SEvalZero  *
408*042d53a7SEvalZero  * @return int BLE error code
409*042d53a7SEvalZero  */
410*042d53a7SEvalZero static int
ble_ll_hci_le_wr_sugg_data_len(uint8_t * cmdbuf)411*042d53a7SEvalZero ble_ll_hci_le_wr_sugg_data_len(uint8_t *cmdbuf)
412*042d53a7SEvalZero {
413*042d53a7SEvalZero     int rc;
414*042d53a7SEvalZero     uint16_t tx_oct;
415*042d53a7SEvalZero     uint16_t tx_time;
416*042d53a7SEvalZero 
417*042d53a7SEvalZero     /* Get suggested octets and time */
418*042d53a7SEvalZero     tx_oct = get_le16(cmdbuf);
419*042d53a7SEvalZero     tx_time = get_le16(cmdbuf + 2);
420*042d53a7SEvalZero 
421*042d53a7SEvalZero     /* If valid, write into suggested and change connection initial times */
422*042d53a7SEvalZero     if (ble_ll_chk_txrx_octets(tx_oct) && ble_ll_chk_txrx_time(tx_time)) {
423*042d53a7SEvalZero         g_ble_ll_conn_params.sugg_tx_octets = (uint8_t)tx_oct;
424*042d53a7SEvalZero         g_ble_ll_conn_params.sugg_tx_time = tx_time;
425*042d53a7SEvalZero 
426*042d53a7SEvalZero         /*
427*042d53a7SEvalZero          * We can disregard host suggestion, but we are a nice controller so
428*042d53a7SEvalZero          * let's use host suggestion, unless they exceed max supported values
429*042d53a7SEvalZero          * in which case we just use our max.
430*042d53a7SEvalZero          */
431*042d53a7SEvalZero         g_ble_ll_conn_params.conn_init_max_tx_octets =
432*042d53a7SEvalZero                         min(tx_oct, g_ble_ll_conn_params.supp_max_tx_octets);
433*042d53a7SEvalZero         g_ble_ll_conn_params.conn_init_max_tx_time =
434*042d53a7SEvalZero                         min(tx_time, g_ble_ll_conn_params.supp_max_tx_time);
435*042d53a7SEvalZero 
436*042d53a7SEvalZero         rc = BLE_ERR_SUCCESS;
437*042d53a7SEvalZero     } else {
438*042d53a7SEvalZero         rc = BLE_ERR_INV_HCI_CMD_PARMS;
439*042d53a7SEvalZero     }
440*042d53a7SEvalZero 
441*042d53a7SEvalZero     return rc;
442*042d53a7SEvalZero }
443*042d53a7SEvalZero 
444*042d53a7SEvalZero /**
445*042d53a7SEvalZero  * HCI read suggested default data length command. Returns the controllers
446*042d53a7SEvalZero  * initial max tx octet/time.
447*042d53a7SEvalZero  *
448*042d53a7SEvalZero  * @param rspbuf Pointer to response buffer
449*042d53a7SEvalZero  * @param rsplen Length of response buffer
450*042d53a7SEvalZero  *
451*042d53a7SEvalZero  * @return int BLE error code
452*042d53a7SEvalZero  */
453*042d53a7SEvalZero static int
ble_ll_hci_le_rd_sugg_data_len(uint8_t * rspbuf,uint8_t * rsplen)454*042d53a7SEvalZero ble_ll_hci_le_rd_sugg_data_len(uint8_t *rspbuf, uint8_t *rsplen)
455*042d53a7SEvalZero {
456*042d53a7SEvalZero     /* Place the data packet length and number of packets in the buffer */
457*042d53a7SEvalZero     put_le16(rspbuf, g_ble_ll_conn_params.sugg_tx_octets);
458*042d53a7SEvalZero     put_le16(rspbuf + 2, g_ble_ll_conn_params.sugg_tx_time);
459*042d53a7SEvalZero     *rsplen = BLE_HCI_RD_SUGG_DATALEN_RSPLEN;
460*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
461*042d53a7SEvalZero }
462*042d53a7SEvalZero 
463*042d53a7SEvalZero /**
464*042d53a7SEvalZero  * HCI read maximum data length command. Returns the controllers max supported
465*042d53a7SEvalZero  * rx/tx octets/times.
466*042d53a7SEvalZero  *
467*042d53a7SEvalZero  * @param rspbuf Pointer to response buffer
468*042d53a7SEvalZero  * @param rsplen Length of response buffer
469*042d53a7SEvalZero  *
470*042d53a7SEvalZero  * @return int BLE error code
471*042d53a7SEvalZero  */
472*042d53a7SEvalZero static int
ble_ll_hci_le_rd_max_data_len(uint8_t * rspbuf,uint8_t * rsplen)473*042d53a7SEvalZero ble_ll_hci_le_rd_max_data_len(uint8_t *rspbuf, uint8_t *rsplen)
474*042d53a7SEvalZero {
475*042d53a7SEvalZero     /* Place the data packet length and number of packets in the buffer */
476*042d53a7SEvalZero     put_le16(rspbuf, g_ble_ll_conn_params.supp_max_tx_octets);
477*042d53a7SEvalZero     put_le16(rspbuf + 2, g_ble_ll_conn_params.supp_max_tx_time);
478*042d53a7SEvalZero     put_le16(rspbuf + 4, g_ble_ll_conn_params.supp_max_rx_octets);
479*042d53a7SEvalZero     put_le16(rspbuf + 6, g_ble_ll_conn_params.supp_max_rx_time);
480*042d53a7SEvalZero     *rsplen = BLE_HCI_RD_MAX_DATALEN_RSPLEN;
481*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
482*042d53a7SEvalZero }
483*042d53a7SEvalZero #endif
484*042d53a7SEvalZero 
485*042d53a7SEvalZero /**
486*042d53a7SEvalZero  * HCI read local supported features command. Returns the features
487*042d53a7SEvalZero  * supported by the controller.
488*042d53a7SEvalZero  *
489*042d53a7SEvalZero  * @param rspbuf Pointer to response buffer
490*042d53a7SEvalZero  * @param rsplen Length of response buffer
491*042d53a7SEvalZero  *
492*042d53a7SEvalZero  * @return int BLE error code
493*042d53a7SEvalZero  */
494*042d53a7SEvalZero static int
ble_ll_hci_le_read_local_features(uint8_t * rspbuf,uint8_t * rsplen)495*042d53a7SEvalZero ble_ll_hci_le_read_local_features(uint8_t *rspbuf, uint8_t *rsplen)
496*042d53a7SEvalZero {
497*042d53a7SEvalZero     /* Add list of supported features. */
498*042d53a7SEvalZero     memset(rspbuf, 0, BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN);
499*042d53a7SEvalZero     put_le32(rspbuf, ble_ll_read_supp_features());
500*042d53a7SEvalZero 
501*042d53a7SEvalZero     *rsplen = BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN;
502*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
503*042d53a7SEvalZero }
504*042d53a7SEvalZero 
505*042d53a7SEvalZero /**
506*042d53a7SEvalZero  * HCI read local supported states command. Returns the states
507*042d53a7SEvalZero  * supported by the controller.
508*042d53a7SEvalZero  *
509*042d53a7SEvalZero  * @param rspbuf Pointer to response buffer
510*042d53a7SEvalZero  * @param rsplen Length of response buffer
511*042d53a7SEvalZero  *
512*042d53a7SEvalZero  * @return int BLE error code
513*042d53a7SEvalZero  */
514*042d53a7SEvalZero static int
ble_ll_hci_le_read_supp_states(uint8_t * rspbuf,uint8_t * rsplen)515*042d53a7SEvalZero ble_ll_hci_le_read_supp_states(uint8_t *rspbuf, uint8_t *rsplen)
516*042d53a7SEvalZero {
517*042d53a7SEvalZero     uint64_t supp_states;
518*042d53a7SEvalZero 
519*042d53a7SEvalZero     /* Add list of supported states. */
520*042d53a7SEvalZero     supp_states = ble_ll_read_supp_states();
521*042d53a7SEvalZero     put_le64(rspbuf, supp_states);
522*042d53a7SEvalZero     *rsplen = BLE_HCI_RD_SUPP_STATES_RSPLEN;
523*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
524*042d53a7SEvalZero }
525*042d53a7SEvalZero 
526*042d53a7SEvalZero /**
527*042d53a7SEvalZero  * Checks to see if a LE event has been disabled by the host.
528*042d53a7SEvalZero  *
529*042d53a7SEvalZero  * @param subev Sub-event code of the LE Meta event. Note that this can
530*042d53a7SEvalZero  * be a value from 0 to 63, inclusive.
531*042d53a7SEvalZero  *
532*042d53a7SEvalZero  * @return uint8_t 0: event is not enabled; otherwise event is enabled.
533*042d53a7SEvalZero  */
534*042d53a7SEvalZero uint8_t
ble_ll_hci_is_le_event_enabled(int subev)535*042d53a7SEvalZero ble_ll_hci_is_le_event_enabled(int subev)
536*042d53a7SEvalZero {
537*042d53a7SEvalZero     uint8_t enabled;
538*042d53a7SEvalZero     uint8_t bytenum;
539*042d53a7SEvalZero     uint8_t bitmask;
540*042d53a7SEvalZero     int bitpos;
541*042d53a7SEvalZero 
542*042d53a7SEvalZero     /* The LE meta event must be enabled for any LE event to be enabled */
543*042d53a7SEvalZero     enabled = 0;
544*042d53a7SEvalZero     bitpos = subev - 1;
545*042d53a7SEvalZero     if (g_ble_ll_hci_event_mask[7] & 0x20) {
546*042d53a7SEvalZero         bytenum = bitpos / 8;
547*042d53a7SEvalZero         bitmask = 1 << (bitpos & 0x7);
548*042d53a7SEvalZero         enabled = g_ble_ll_hci_le_event_mask[bytenum] & bitmask;
549*042d53a7SEvalZero     }
550*042d53a7SEvalZero 
551*042d53a7SEvalZero     return enabled;
552*042d53a7SEvalZero }
553*042d53a7SEvalZero 
554*042d53a7SEvalZero /**
555*042d53a7SEvalZero  * Checks to see if an event has been disabled by the host.
556*042d53a7SEvalZero  *
557*042d53a7SEvalZero  * NOTE: there are two "pages" of event masks; the first page is for event
558*042d53a7SEvalZero  * codes between 0 and 63 and the second page is for event codes 64 and
559*042d53a7SEvalZero  * greater.
560*042d53a7SEvalZero  *
561*042d53a7SEvalZero  * @param evcode This is the event code for the event.
562*042d53a7SEvalZero  *
563*042d53a7SEvalZero  * @return uint8_t 0: event is not enabled; otherwise event is enabled.
564*042d53a7SEvalZero  */
565*042d53a7SEvalZero uint8_t
ble_ll_hci_is_event_enabled(int evcode)566*042d53a7SEvalZero ble_ll_hci_is_event_enabled(int evcode)
567*042d53a7SEvalZero {
568*042d53a7SEvalZero     uint8_t enabled;
569*042d53a7SEvalZero     uint8_t bytenum;
570*042d53a7SEvalZero     uint8_t bitmask;
571*042d53a7SEvalZero     uint8_t *evptr;
572*042d53a7SEvalZero     int bitpos;
573*042d53a7SEvalZero 
574*042d53a7SEvalZero     if (evcode >= 64) {
575*042d53a7SEvalZero         evptr = &g_ble_ll_hci_event_mask2[0];
576*042d53a7SEvalZero         bitpos = evcode - 64;
577*042d53a7SEvalZero     } else {
578*042d53a7SEvalZero         evptr = &g_ble_ll_hci_event_mask[0];
579*042d53a7SEvalZero         bitpos = evcode - 1;
580*042d53a7SEvalZero     }
581*042d53a7SEvalZero 
582*042d53a7SEvalZero     bytenum = bitpos / 8;
583*042d53a7SEvalZero     bitmask = 1 << (bitpos & 0x7);
584*042d53a7SEvalZero     enabled = evptr[bytenum] & bitmask;
585*042d53a7SEvalZero 
586*042d53a7SEvalZero     return enabled;
587*042d53a7SEvalZero }
588*042d53a7SEvalZero 
589*042d53a7SEvalZero /**
590*042d53a7SEvalZero  * Called to determine if the reply to the command should be a command complete
591*042d53a7SEvalZero  * event or a command status event.
592*042d53a7SEvalZero  *
593*042d53a7SEvalZero  * @param ocf
594*042d53a7SEvalZero  *
595*042d53a7SEvalZero  * @return int 0: return command complete; 1: return command status event
596*042d53a7SEvalZero  */
597*042d53a7SEvalZero static int
ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf)598*042d53a7SEvalZero ble_ll_hci_le_cmd_send_cmd_status(uint16_t ocf)
599*042d53a7SEvalZero {
600*042d53a7SEvalZero     int rc;
601*042d53a7SEvalZero 
602*042d53a7SEvalZero     switch (ocf) {
603*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_REM_FEAT:
604*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CREATE_CONN:
605*042d53a7SEvalZero     case BLE_HCI_OCF_LE_EXT_CREATE_CONN:
606*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CONN_UPDATE:
607*042d53a7SEvalZero     case BLE_HCI_OCF_LE_START_ENCRYPT:
608*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_P256_PUBKEY:
609*042d53a7SEvalZero     case BLE_HCI_OCF_LE_GEN_DHKEY:
610*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_PHY:
611*042d53a7SEvalZero         rc = 1;
612*042d53a7SEvalZero         break;
613*042d53a7SEvalZero     default:
614*042d53a7SEvalZero         rc = 0;
615*042d53a7SEvalZero         break;
616*042d53a7SEvalZero     }
617*042d53a7SEvalZero     return rc;
618*042d53a7SEvalZero }
619*042d53a7SEvalZero 
620*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
621*042d53a7SEvalZero /** HCI LE read maximum advertising data length command. Returns the controllers
622*042d53a7SEvalZero * max supported advertising data length;
623*042d53a7SEvalZero *
624*042d53a7SEvalZero * @param rspbuf Pointer to response buffer
625*042d53a7SEvalZero * @param rsplen Length of response buffer
626*042d53a7SEvalZero *
627*042d53a7SEvalZero * @return int BLE error code
628*042d53a7SEvalZero */
629*042d53a7SEvalZero static int
ble_ll_adv_rd_max_adv_data_len(uint8_t * rspbuf,uint8_t * rsplen)630*042d53a7SEvalZero ble_ll_adv_rd_max_adv_data_len(uint8_t *rspbuf, uint8_t *rsplen)
631*042d53a7SEvalZero {
632*042d53a7SEvalZero     put_le16(rspbuf, BLE_ADV_DATA_MAX_LEN);
633*042d53a7SEvalZero     *rsplen = BLE_HCI_RD_MAX_ADV_DATA_LEN;
634*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
635*042d53a7SEvalZero }
636*042d53a7SEvalZero 
637*042d53a7SEvalZero /**
638*042d53a7SEvalZero  * HCI LE read number of supported advertising sets
639*042d53a7SEvalZero  *
640*042d53a7SEvalZero  * @param rspbuf Pointer to response buffer
641*042d53a7SEvalZero  * @param rsplen Length of response buffer
642*042d53a7SEvalZero  *
643*042d53a7SEvalZero  * @return int BLE error code
644*042d53a7SEvalZero  */
645*042d53a7SEvalZero static int
ble_ll_adv_rd_sup_adv_sets(uint8_t * rspbuf,uint8_t * rsplen)646*042d53a7SEvalZero ble_ll_adv_rd_sup_adv_sets(uint8_t *rspbuf, uint8_t *rsplen)
647*042d53a7SEvalZero {
648*042d53a7SEvalZero     rspbuf[0] = BLE_ADV_INSTANCES;
649*042d53a7SEvalZero     *rsplen = BLE_HCI_RD_NR_SUP_ADV_SETS;
650*042d53a7SEvalZero     return BLE_ERR_SUCCESS;
651*042d53a7SEvalZero }
652*042d53a7SEvalZero 
653*042d53a7SEvalZero static int
ble_ll_ext_adv_set_remove(uint8_t * cmd)654*042d53a7SEvalZero ble_ll_ext_adv_set_remove(uint8_t *cmd)
655*042d53a7SEvalZero {
656*042d53a7SEvalZero     return ble_ll_adv_remove(cmd[0]);
657*042d53a7SEvalZero }
658*042d53a7SEvalZero 
659*042d53a7SEvalZero static bool
ble_ll_is_valid_adv_mode(uint8_t ocf)660*042d53a7SEvalZero ble_ll_is_valid_adv_mode(uint8_t ocf)
661*042d53a7SEvalZero {
662*042d53a7SEvalZero     /*
663*042d53a7SEvalZero      * If, since the last power-on or reset, the Host has ever issued a legacy
664*042d53a7SEvalZero      * advertising command and then issues an extended advertising command, or
665*042d53a7SEvalZero      * has ever issued an extended advertising command and then issues a legacy
666*042d53a7SEvalZero      * advertising command, the Controller shall return the error code Command
667*042d53a7SEvalZero      * Disallowed (0x0C).
668*042d53a7SEvalZero     */
669*042d53a7SEvalZero 
670*042d53a7SEvalZero     switch(ocf) {
671*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CREATE_CONN:
672*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_ADV_PARAMS:
673*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_ADV_ENABLE:
674*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_ADV_DATA:
675*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_SCAN_PARAMS:
676*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_SCAN_ENABLE:
677*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA:
678*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR:
679*042d53a7SEvalZero         if (hci_adv_mode == ADV_MODE_EXT) {
680*042d53a7SEvalZero             return false;
681*042d53a7SEvalZero         }
682*042d53a7SEvalZero 
683*042d53a7SEvalZero         hci_adv_mode = ADV_MODE_LEGACY;
684*042d53a7SEvalZero         break;
685*042d53a7SEvalZero     case BLE_HCI_OCF_LE_EXT_CREATE_CONN:
686*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_ADV_DATA:
687*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE:
688*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM:
689*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE:
690*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM:
691*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA:
692*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_MAX_ADV_DATA_LEN:
693*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS:
694*042d53a7SEvalZero     case BLE_HCI_OCF_LE_REMOVE_ADV_SET:
695*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CLEAR_ADV_SETS:
696*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_PER_ADV_PARAMS:
697*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_PER_ADV_DATA:
698*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_PER_ADV_ENABLE:
699*042d53a7SEvalZero     case BLE_HCI_OCF_LE_PER_ADV_CREATE_SYNC:
700*042d53a7SEvalZero     case BLE_HCI_OCF_LE_PER_ADV_CREATE_SYNC_CANCEL:
701*042d53a7SEvalZero     case BLE_HCI_OCF_LE_PER_ADV_TERM_SYNC:
702*042d53a7SEvalZero     case BLE_HCI_OCF_LE_ADD_DEV_TO_PER_ADV_LIST:
703*042d53a7SEvalZero     case BLE_HCI_OCF_LE_REM_DEV_FROM_PER_ADV_LIST:
704*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CLEAR_PER_ADV_LIST:
705*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_PER_ADV_LIST_SIZE:
706*042d53a7SEvalZero         if (hci_adv_mode == ADV_MODE_LEGACY) {
707*042d53a7SEvalZero             return false;
708*042d53a7SEvalZero         }
709*042d53a7SEvalZero 
710*042d53a7SEvalZero         hci_adv_mode = ADV_MODE_EXT;
711*042d53a7SEvalZero         break;
712*042d53a7SEvalZero     default:
713*042d53a7SEvalZero         break;
714*042d53a7SEvalZero     }
715*042d53a7SEvalZero 
716*042d53a7SEvalZero     return true;
717*042d53a7SEvalZero }
718*042d53a7SEvalZero #endif
719*042d53a7SEvalZero 
720*042d53a7SEvalZero /**
721*042d53a7SEvalZero  * Process a LE command sent from the host to the controller. The HCI command
722*042d53a7SEvalZero  * has a 3 byte command header followed by data. The header is:
723*042d53a7SEvalZero  *  -> opcode (2 bytes)
724*042d53a7SEvalZero  *  -> Length of parameters (1 byte; does include command header bytes).
725*042d53a7SEvalZero  *
726*042d53a7SEvalZero  * @param cmdbuf Pointer to command buffer. Points to start of command header.
727*042d53a7SEvalZero  * @param ocf    Opcode command field.
728*042d53a7SEvalZero  * @param *rsplen Pointer to length of response
729*042d53a7SEvalZero  *
730*042d53a7SEvalZero  * @return int  This function returns a BLE error code. If a command status
731*042d53a7SEvalZero  *              event should be returned as opposed to command complete,
732*042d53a7SEvalZero  *              256 gets added to the return value.
733*042d53a7SEvalZero  */
734*042d53a7SEvalZero static int
ble_ll_hci_le_cmd_proc(uint8_t * cmdbuf,uint16_t ocf,uint8_t * rsplen,ble_ll_hci_post_cmd_complete_cb * cb)735*042d53a7SEvalZero ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen,
736*042d53a7SEvalZero                                             ble_ll_hci_post_cmd_complete_cb *cb)
737*042d53a7SEvalZero {
738*042d53a7SEvalZero     int rc;
739*042d53a7SEvalZero     uint8_t len;
740*042d53a7SEvalZero     uint8_t *rspbuf;
741*042d53a7SEvalZero 
742*042d53a7SEvalZero     /* Assume error; if all pass rc gets set to 0 */
743*042d53a7SEvalZero     rc = BLE_ERR_INV_HCI_CMD_PARMS;
744*042d53a7SEvalZero 
745*042d53a7SEvalZero     /* Get length from command */
746*042d53a7SEvalZero     len = cmdbuf[sizeof(uint16_t)];
747*042d53a7SEvalZero 
748*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
749*042d53a7SEvalZero     if (!ble_ll_is_valid_adv_mode(ocf)) {
750*042d53a7SEvalZero         rc = BLE_ERR_CMD_DISALLOWED;
751*042d53a7SEvalZero         goto ll_hci_le_cmd_exit;
752*042d53a7SEvalZero     }
753*042d53a7SEvalZero #endif
754*042d53a7SEvalZero 
755*042d53a7SEvalZero     /*
756*042d53a7SEvalZero      * The command response pointer points into the same buffer as the
757*042d53a7SEvalZero      * command data itself. That is fine, as each command reads all the data
758*042d53a7SEvalZero      * before crafting a response.
759*042d53a7SEvalZero      */
760*042d53a7SEvalZero     rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN;
761*042d53a7SEvalZero 
762*042d53a7SEvalZero     /* Move past HCI command header */
763*042d53a7SEvalZero     cmdbuf += BLE_HCI_CMD_HDR_LEN;
764*042d53a7SEvalZero 
765*042d53a7SEvalZero     switch (ocf) {
766*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EVENT_MASK:
767*042d53a7SEvalZero         if (len == BLE_HCI_SET_LE_EVENT_MASK_LEN) {
768*042d53a7SEvalZero             rc = ble_ll_hci_set_le_event_mask(cmdbuf);
769*042d53a7SEvalZero         }
770*042d53a7SEvalZero         break;
771*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_BUF_SIZE:
772*042d53a7SEvalZero         if (len == BLE_HCI_RD_BUF_SIZE_LEN) {
773*042d53a7SEvalZero             rc = ble_ll_hci_le_read_bufsize(rspbuf, rsplen);
774*042d53a7SEvalZero         }
775*042d53a7SEvalZero         break;
776*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT:
777*042d53a7SEvalZero         if (len == 0) {
778*042d53a7SEvalZero             rc = ble_ll_hci_le_read_local_features(rspbuf, rsplen);
779*042d53a7SEvalZero         }
780*042d53a7SEvalZero         break;
781*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_RAND_ADDR:
782*042d53a7SEvalZero         if (len == BLE_HCI_SET_RAND_ADDR_LEN) {
783*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
784*042d53a7SEvalZero             rc = ble_ll_set_random_addr(cmdbuf, hci_adv_mode == ADV_MODE_EXT);
785*042d53a7SEvalZero #else
786*042d53a7SEvalZero             rc = ble_ll_set_random_addr(cmdbuf, false);
787*042d53a7SEvalZero #endif
788*042d53a7SEvalZero         }
789*042d53a7SEvalZero         break;
790*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_ADV_PARAMS:
791*042d53a7SEvalZero         if (len == BLE_HCI_SET_ADV_PARAM_LEN) {
792*042d53a7SEvalZero             rc = ble_ll_adv_set_adv_params(cmdbuf);
793*042d53a7SEvalZero         }
794*042d53a7SEvalZero         break;
795*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR:
796*042d53a7SEvalZero         if (len == 0) {
797*042d53a7SEvalZero             rc = ble_ll_adv_read_txpwr(rspbuf, rsplen);
798*042d53a7SEvalZero         }
799*042d53a7SEvalZero         break;
800*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_ADV_DATA:
801*042d53a7SEvalZero         if (len == BLE_HCI_SET_ADV_DATA_LEN) {
802*042d53a7SEvalZero             rc = ble_ll_adv_set_adv_data(cmdbuf, len, 0,
803*042d53a7SEvalZero                                      BLE_HCI_LE_SET_EXT_ADV_DATA_OPER_COMPLETE);
804*042d53a7SEvalZero         }
805*042d53a7SEvalZero         break;
806*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_SCAN_RSP_DATA:
807*042d53a7SEvalZero         if (len == BLE_HCI_SET_SCAN_RSP_DATA_LEN) {
808*042d53a7SEvalZero             rc = ble_ll_adv_set_scan_rsp_data(cmdbuf, len, 0,
809*042d53a7SEvalZero                                 BLE_HCI_LE_SET_EXT_SCAN_RSP_DATA_OPER_COMPLETE);
810*042d53a7SEvalZero         }
811*042d53a7SEvalZero         break;
812*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_ADV_ENABLE:
813*042d53a7SEvalZero         if (len == BLE_HCI_SET_ADV_ENABLE_LEN) {
814*042d53a7SEvalZero             rc = ble_ll_adv_set_enable(0, cmdbuf[0], -1, 0);
815*042d53a7SEvalZero         }
816*042d53a7SEvalZero         break;
817*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_SCAN_PARAMS:
818*042d53a7SEvalZero         if (len == BLE_HCI_SET_SCAN_PARAM_LEN) {
819*042d53a7SEvalZero             rc = ble_ll_scan_set_scan_params(cmdbuf);
820*042d53a7SEvalZero         }
821*042d53a7SEvalZero         break;
822*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_SCAN_ENABLE:
823*042d53a7SEvalZero         if (len == BLE_HCI_SET_SCAN_ENABLE_LEN) {
824*042d53a7SEvalZero             rc = ble_ll_scan_set_enable(cmdbuf, 0);
825*042d53a7SEvalZero         }
826*042d53a7SEvalZero         break;
827*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CREATE_CONN:
828*042d53a7SEvalZero         if (len == BLE_HCI_CREATE_CONN_LEN) {
829*042d53a7SEvalZero             rc = ble_ll_conn_create(cmdbuf);
830*042d53a7SEvalZero         }
831*042d53a7SEvalZero         break;
832*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL:
833*042d53a7SEvalZero         if (len == 0) {
834*042d53a7SEvalZero             rc = ble_ll_conn_create_cancel(cb);
835*042d53a7SEvalZero         }
836*042d53a7SEvalZero         break;
837*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_WHITE_LIST_SIZE:
838*042d53a7SEvalZero         if (len == 0) {
839*042d53a7SEvalZero             rc = ble_ll_whitelist_read_size(rspbuf, rsplen);
840*042d53a7SEvalZero         }
841*042d53a7SEvalZero         break;
842*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CLEAR_WHITE_LIST:
843*042d53a7SEvalZero         if (len == 0) {
844*042d53a7SEvalZero             rc = ble_ll_whitelist_clear();
845*042d53a7SEvalZero         }
846*042d53a7SEvalZero         break;
847*042d53a7SEvalZero     case BLE_HCI_OCF_LE_ADD_WHITE_LIST:
848*042d53a7SEvalZero         if (len == BLE_HCI_ADD_WHITE_LIST_LEN) {
849*042d53a7SEvalZero             rc = ble_ll_whitelist_add(cmdbuf + 1, cmdbuf[0]);
850*042d53a7SEvalZero         }
851*042d53a7SEvalZero         break;
852*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RMV_WHITE_LIST:
853*042d53a7SEvalZero         if (len == BLE_HCI_RMV_WHITE_LIST_LEN) {
854*042d53a7SEvalZero             rc = ble_ll_whitelist_rmv(cmdbuf + 1, cmdbuf[0]);
855*042d53a7SEvalZero         }
856*042d53a7SEvalZero         break;
857*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CONN_UPDATE:
858*042d53a7SEvalZero         if (len == BLE_HCI_CONN_UPDATE_LEN) {
859*042d53a7SEvalZero             rc = ble_ll_conn_hci_update(cmdbuf);
860*042d53a7SEvalZero         }
861*042d53a7SEvalZero         break;
862*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS:
863*042d53a7SEvalZero         if (BLE_HCI_SET_HOST_CHAN_CLASS_LEN) {
864*042d53a7SEvalZero             rc = ble_ll_conn_hci_set_chan_class(cmdbuf);
865*042d53a7SEvalZero         }
866*042d53a7SEvalZero         break;
867*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_CHAN_MAP:
868*042d53a7SEvalZero         if (len == BLE_HCI_RD_CHANMAP_LEN) {
869*042d53a7SEvalZero             rc = ble_ll_conn_hci_rd_chan_map(cmdbuf, rspbuf, rsplen);
870*042d53a7SEvalZero         }
871*042d53a7SEvalZero         break;
872*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_REM_FEAT:
873*042d53a7SEvalZero         if (len == BLE_HCI_CONN_RD_REM_FEAT_LEN) {
874*042d53a7SEvalZero             rc = ble_ll_conn_hci_read_rem_features(cmdbuf);
875*042d53a7SEvalZero         }
876*042d53a7SEvalZero         break;
877*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
878*042d53a7SEvalZero     case BLE_HCI_OCF_LE_ENCRYPT:
879*042d53a7SEvalZero         if (len == BLE_HCI_LE_ENCRYPT_LEN) {
880*042d53a7SEvalZero             rc = ble_ll_hci_le_encrypt(cmdbuf, rspbuf, rsplen);
881*042d53a7SEvalZero         }
882*042d53a7SEvalZero         break;
883*042d53a7SEvalZero #endif
884*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RAND:
885*042d53a7SEvalZero         if (len == 0) {
886*042d53a7SEvalZero             rc = ble_ll_hci_le_rand(rspbuf, rsplen);
887*042d53a7SEvalZero         }
888*042d53a7SEvalZero         break;
889*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
890*042d53a7SEvalZero     case BLE_HCI_OCF_LE_START_ENCRYPT:
891*042d53a7SEvalZero         if (len == BLE_HCI_LE_START_ENCRYPT_LEN) {
892*042d53a7SEvalZero             rc = ble_ll_conn_hci_le_start_encrypt(cmdbuf);
893*042d53a7SEvalZero         }
894*042d53a7SEvalZero         break;
895*042d53a7SEvalZero     case BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY:
896*042d53a7SEvalZero         if (len == BLE_HCI_LT_KEY_REQ_REPLY_LEN) {
897*042d53a7SEvalZero             rc = ble_ll_conn_hci_le_ltk_reply(cmdbuf, rspbuf, rsplen);
898*042d53a7SEvalZero         }
899*042d53a7SEvalZero         break;
900*042d53a7SEvalZero     case BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY:
901*042d53a7SEvalZero         if (len == BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN) {
902*042d53a7SEvalZero             rc = ble_ll_conn_hci_le_ltk_neg_reply(cmdbuf, rspbuf, rsplen);
903*042d53a7SEvalZero         }
904*042d53a7SEvalZero         break;
905*042d53a7SEvalZero #endif
906*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_SUPP_STATES :
907*042d53a7SEvalZero         if (len == 0) {
908*042d53a7SEvalZero             rc = ble_ll_hci_le_read_supp_states(rspbuf, rsplen);
909*042d53a7SEvalZero         }
910*042d53a7SEvalZero         break;
911*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
912*042d53a7SEvalZero     case BLE_HCI_OCF_LE_TX_TEST:
913*042d53a7SEvalZero         if (len == BLE_HCI_TX_TEST_LEN) {
914*042d53a7SEvalZero             rc = ble_ll_dtm_tx_test(cmdbuf, false);
915*042d53a7SEvalZero         }
916*042d53a7SEvalZero         break;
917*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RX_TEST:
918*042d53a7SEvalZero         if (len == BLE_HCI_RX_TEST_LEN) {
919*042d53a7SEvalZero             rc = ble_ll_dtm_rx_test(cmdbuf, false);
920*042d53a7SEvalZero         }
921*042d53a7SEvalZero         break;
922*042d53a7SEvalZero     case BLE_HCI_OCF_LE_TEST_END:
923*042d53a7SEvalZero         if (len == 0) {
924*042d53a7SEvalZero             rc = ble_ll_dtm_end_test(rspbuf, rsplen);
925*042d53a7SEvalZero         }
926*042d53a7SEvalZero         break;
927*042d53a7SEvalZero #endif
928*042d53a7SEvalZero     case BLE_HCI_OCF_LE_REM_CONN_PARAM_RR:
929*042d53a7SEvalZero         if (len == BLE_HCI_CONN_PARAM_REPLY_LEN) {
930*042d53a7SEvalZero             rc = ble_ll_conn_hci_param_reply(cmdbuf, 1, rspbuf, rsplen);
931*042d53a7SEvalZero         }
932*042d53a7SEvalZero         break;
933*042d53a7SEvalZero     case BLE_HCI_OCF_LE_REM_CONN_PARAM_NRR:
934*042d53a7SEvalZero         if (len == BLE_HCI_CONN_PARAM_NEG_REPLY_LEN) {
935*042d53a7SEvalZero             rc = ble_ll_conn_hci_param_reply(cmdbuf, 0, rspbuf, rsplen);
936*042d53a7SEvalZero         }
937*042d53a7SEvalZero         break;
938*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) == 1)
939*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_DATA_LEN:
940*042d53a7SEvalZero         if (len == BLE_HCI_SET_DATALEN_LEN) {
941*042d53a7SEvalZero             rc = ble_ll_conn_hci_set_data_len(cmdbuf, rspbuf, rsplen);
942*042d53a7SEvalZero         }
943*042d53a7SEvalZero         break;
944*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN:
945*042d53a7SEvalZero         if (len == 0) {
946*042d53a7SEvalZero             rc = ble_ll_hci_le_rd_sugg_data_len(rspbuf, rsplen);
947*042d53a7SEvalZero         }
948*042d53a7SEvalZero         break;
949*042d53a7SEvalZero     case BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN:
950*042d53a7SEvalZero         if (len == BLE_HCI_WR_SUGG_DATALEN_LEN) {
951*042d53a7SEvalZero             rc = ble_ll_hci_le_wr_sugg_data_len(cmdbuf);
952*042d53a7SEvalZero         }
953*042d53a7SEvalZero         break;
954*042d53a7SEvalZero #endif
955*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
956*042d53a7SEvalZero     case BLE_HCI_OCF_LE_ADD_RESOLV_LIST :
957*042d53a7SEvalZero         if (len == BLE_HCI_ADD_TO_RESOLV_LIST_LEN) {
958*042d53a7SEvalZero             rc = ble_ll_resolv_list_add(cmdbuf);
959*042d53a7SEvalZero         }
960*042d53a7SEvalZero         break;
961*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RMV_RESOLV_LIST:
962*042d53a7SEvalZero         if (len == BLE_HCI_RMV_FROM_RESOLV_LIST_LEN) {
963*042d53a7SEvalZero             rc = ble_ll_resolv_list_rmv(cmdbuf);
964*042d53a7SEvalZero         }
965*042d53a7SEvalZero         break;
966*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CLR_RESOLV_LIST:
967*042d53a7SEvalZero         if (len == 0) {
968*042d53a7SEvalZero             rc = ble_ll_resolv_list_clr();
969*042d53a7SEvalZero         }
970*042d53a7SEvalZero         break;
971*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_RESOLV_LIST_SIZE:
972*042d53a7SEvalZero         if (len == 0) {
973*042d53a7SEvalZero             rc = ble_ll_resolv_list_read_size(rspbuf, rsplen);
974*042d53a7SEvalZero         }
975*042d53a7SEvalZero         break;
976*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_PEER_RESOLV_ADDR:
977*042d53a7SEvalZero         if (len == BLE_HCI_RD_PEER_RESOLV_ADDR_LEN) {
978*042d53a7SEvalZero             rc = ble_ll_resolv_peer_addr_rd(cmdbuf, rspbuf, rsplen);
979*042d53a7SEvalZero         }
980*042d53a7SEvalZero         break;
981*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_LOCAL_RESOLV_ADDR:
982*042d53a7SEvalZero         if(len == BLE_HCI_RD_LOC_RESOLV_ADDR_LEN) {
983*042d53a7SEvalZero             rc = ble_ll_resolv_local_addr_rd(cmdbuf, rspbuf, rsplen);
984*042d53a7SEvalZero         }
985*042d53a7SEvalZero         break;
986*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_ADDR_RES_EN:
987*042d53a7SEvalZero         if (len == BLE_HCI_SET_ADDR_RESOL_ENA_LEN) {
988*042d53a7SEvalZero             rc = ble_ll_resolv_enable_cmd(cmdbuf);
989*042d53a7SEvalZero         }
990*042d53a7SEvalZero         break;
991*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_RPA_TMO:
992*042d53a7SEvalZero         if (len == BLE_HCI_SET_RESOLV_PRIV_ADDR_TO_LEN) {
993*042d53a7SEvalZero             rc = ble_ll_resolv_set_rpa_tmo(cmdbuf);
994*042d53a7SEvalZero         }
995*042d53a7SEvalZero         break;
996*042d53a7SEvalZero #endif
997*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) == 1)
998*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_MAX_DATA_LEN:
999*042d53a7SEvalZero         if (len == 0) {
1000*042d53a7SEvalZero             rc = ble_ll_hci_le_rd_max_data_len(rspbuf, rsplen);
1001*042d53a7SEvalZero         }
1002*042d53a7SEvalZero         break;
1003*042d53a7SEvalZero #endif
1004*042d53a7SEvalZero #if (BLE_LL_BT5_PHY_SUPPORTED == 1)
1005*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_PHY:
1006*042d53a7SEvalZero         if (len == BLE_HCI_LE_RD_PHY_LEN) {
1007*042d53a7SEvalZero             rc = ble_ll_conn_hci_le_rd_phy(cmdbuf, rspbuf, rsplen);
1008*042d53a7SEvalZero         }
1009*042d53a7SEvalZero         break;
1010*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_DEFAULT_PHY:
1011*042d53a7SEvalZero         if (len == BLE_HCI_LE_SET_DEFAULT_PHY_LEN) {
1012*042d53a7SEvalZero             rc = ble_ll_hci_le_set_def_phy(cmdbuf);
1013*042d53a7SEvalZero         }
1014*042d53a7SEvalZero         break;
1015*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_PHY:
1016*042d53a7SEvalZero         if (len == BLE_HCI_LE_SET_PHY_LEN) {
1017*042d53a7SEvalZero             rc = ble_ll_conn_hci_le_set_phy(cmdbuf);
1018*042d53a7SEvalZero         }
1019*042d53a7SEvalZero         break;
1020*042d53a7SEvalZero #endif
1021*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
1022*042d53a7SEvalZero     case BLE_HCI_OCF_LE_ENH_RX_TEST:
1023*042d53a7SEvalZero         if (len == BLE_HCI_LE_ENH_RX_TEST_LEN) {
1024*042d53a7SEvalZero             rc = ble_ll_dtm_rx_test(cmdbuf, true);
1025*042d53a7SEvalZero         }
1026*042d53a7SEvalZero         break;
1027*042d53a7SEvalZero     case BLE_HCI_OCF_LE_ENH_TX_TEST:
1028*042d53a7SEvalZero         if (len == BLE_HCI_LE_ENH_TX_TEST_LEN) {
1029*042d53a7SEvalZero             rc = ble_ll_dtm_tx_test(cmdbuf, true);
1030*042d53a7SEvalZero         }
1031*042d53a7SEvalZero         break;
1032*042d53a7SEvalZero #endif
1033*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) == 1)
1034*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_ADV_SET_RND_ADDR:
1035*042d53a7SEvalZero         if (len == BLE_HCI_LE_SET_ADV_SET_RND_ADDR_LEN) {
1036*042d53a7SEvalZero             rc = ble_ll_adv_set_random_addr(cmdbuf + 1, cmdbuf[0]);
1037*042d53a7SEvalZero         }
1038*042d53a7SEvalZero         break;
1039*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_ADV_PARAM:
1040*042d53a7SEvalZero         if (len == BLE_HCI_LE_SET_EXT_ADV_PARAM_LEN) {
1041*042d53a7SEvalZero             rc = ble_ll_adv_ext_set_param(cmdbuf, rspbuf, rsplen);
1042*042d53a7SEvalZero         }
1043*042d53a7SEvalZero         break;
1044*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_ADV_DATA:
1045*042d53a7SEvalZero         /* variable length */
1046*042d53a7SEvalZero         rc = ble_ll_adv_ext_set_adv_data(cmdbuf, len);
1047*042d53a7SEvalZero         break;
1048*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_SCAN_RSP_DATA:
1049*042d53a7SEvalZero         /* variable length */
1050*042d53a7SEvalZero         rc = ble_ll_adv_ext_set_scan_rsp(cmdbuf, len);
1051*042d53a7SEvalZero         break;
1052*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_ADV_ENABLE:
1053*042d53a7SEvalZero         /* variable length */
1054*042d53a7SEvalZero         rc =  ble_ll_adv_ext_set_enable(cmdbuf, len);
1055*042d53a7SEvalZero         break;
1056*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_MAX_ADV_DATA_LEN:
1057*042d53a7SEvalZero         if (len == 0) {
1058*042d53a7SEvalZero             rc = ble_ll_adv_rd_max_adv_data_len(rspbuf, rsplen);
1059*042d53a7SEvalZero         }
1060*042d53a7SEvalZero         break;
1061*042d53a7SEvalZero     case BLE_HCI_OCF_LE_RD_NUM_OF_ADV_SETS:
1062*042d53a7SEvalZero         if (len == 0) {
1063*042d53a7SEvalZero             rc = ble_ll_adv_rd_sup_adv_sets(rspbuf, rsplen);
1064*042d53a7SEvalZero         }
1065*042d53a7SEvalZero         break;
1066*042d53a7SEvalZero     case BLE_HCI_OCF_LE_REMOVE_ADV_SET:
1067*042d53a7SEvalZero         if (len == BLE_HCI_LE_REMOVE_ADV_SET_LEN) {
1068*042d53a7SEvalZero             rc =  ble_ll_ext_adv_set_remove(cmdbuf);
1069*042d53a7SEvalZero         }
1070*042d53a7SEvalZero         break;
1071*042d53a7SEvalZero     case BLE_HCI_OCF_LE_CLEAR_ADV_SETS:
1072*042d53a7SEvalZero         if (len == 0) {
1073*042d53a7SEvalZero             rc =  ble_ll_adv_clear_all();
1074*042d53a7SEvalZero         }
1075*042d53a7SEvalZero         break;
1076*042d53a7SEvalZero #endif
1077*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1078*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_SCAN_PARAM:
1079*042d53a7SEvalZero         /* variable length */
1080*042d53a7SEvalZero         rc = ble_ll_set_ext_scan_params(cmdbuf, len);
1081*042d53a7SEvalZero         break;
1082*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_EXT_SCAN_ENABLE:
1083*042d53a7SEvalZero         if (len == BLE_HCI_LE_SET_EXT_SCAN_ENABLE_LEN) {
1084*042d53a7SEvalZero             rc = ble_ll_scan_set_enable(cmdbuf, 1);
1085*042d53a7SEvalZero         }
1086*042d53a7SEvalZero         break;
1087*042d53a7SEvalZero     case BLE_HCI_OCF_LE_EXT_CREATE_CONN:
1088*042d53a7SEvalZero         /* variable length */
1089*042d53a7SEvalZero         rc = ble_ll_ext_conn_create(cmdbuf, len);
1090*042d53a7SEvalZero         break;
1091*042d53a7SEvalZero #endif
1092*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
1093*042d53a7SEvalZero     case BLE_HCI_OCF_LE_SET_PRIVACY_MODE:
1094*042d53a7SEvalZero         if (len == BLE_HCI_LE_SET_PRIVACY_MODE_LEN) {
1095*042d53a7SEvalZero             rc = ble_ll_resolve_set_priv_mode(cmdbuf);
1096*042d53a7SEvalZero         }
1097*042d53a7SEvalZero         break;
1098*042d53a7SEvalZero #endif
1099*042d53a7SEvalZero     default:
1100*042d53a7SEvalZero         rc = BLE_ERR_UNKNOWN_HCI_CMD;
1101*042d53a7SEvalZero         break;
1102*042d53a7SEvalZero     }
1103*042d53a7SEvalZero 
1104*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1105*042d53a7SEvalZero ll_hci_le_cmd_exit:
1106*042d53a7SEvalZero #endif
1107*042d53a7SEvalZero     /*
1108*042d53a7SEvalZero      * This code is here because we add 256 to the return code to denote
1109*042d53a7SEvalZero      * that the reply to this command should be command status (as opposed to
1110*042d53a7SEvalZero      * command complete).
1111*042d53a7SEvalZero      *
1112*042d53a7SEvalZero      * For unknown HCI command let us return always command status as per
1113*042d53a7SEvalZero      * specification Bluetooth 5, Vol. 2, Chapter 4.4
1114*042d53a7SEvalZero      */
1115*042d53a7SEvalZero     if (ble_ll_hci_le_cmd_send_cmd_status(ocf) || rc == BLE_ERR_UNKNOWN_HCI_CMD) {
1116*042d53a7SEvalZero         rc += (BLE_ERR_MAX + 1);
1117*042d53a7SEvalZero     }
1118*042d53a7SEvalZero 
1119*042d53a7SEvalZero     return rc;
1120*042d53a7SEvalZero }
1121*042d53a7SEvalZero 
1122*042d53a7SEvalZero /**
1123*042d53a7SEvalZero  * Process a link control command sent from the host to the controller. The HCI
1124*042d53a7SEvalZero  * command has a 3 byte command header followed by data. The header is:
1125*042d53a7SEvalZero  *  -> opcode (2 bytes)
1126*042d53a7SEvalZero  *  -> Length of parameters (1 byte; does include command header bytes).
1127*042d53a7SEvalZero  *
1128*042d53a7SEvalZero  * @param cmdbuf Pointer to command buffer. Points to start of command header.
1129*042d53a7SEvalZero  * @param ocf    Opcode command field.
1130*042d53a7SEvalZero  * @param *rsplen Pointer to length of response
1131*042d53a7SEvalZero  *
1132*042d53a7SEvalZero  * @return int  This function returns a BLE error code. If a command status
1133*042d53a7SEvalZero  *              event should be returned as opposed to command complete,
1134*042d53a7SEvalZero  *              256 gets added to the return value.
1135*042d53a7SEvalZero  */
1136*042d53a7SEvalZero static int
ble_ll_hci_link_ctrl_cmd_proc(uint8_t * cmdbuf,uint16_t ocf,uint8_t * rsplen)1137*042d53a7SEvalZero ble_ll_hci_link_ctrl_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
1138*042d53a7SEvalZero {
1139*042d53a7SEvalZero     int rc;
1140*042d53a7SEvalZero     uint8_t len;
1141*042d53a7SEvalZero 
1142*042d53a7SEvalZero     /* Assume error; if all pass rc gets set to 0 */
1143*042d53a7SEvalZero     rc = BLE_ERR_INV_HCI_CMD_PARMS;
1144*042d53a7SEvalZero 
1145*042d53a7SEvalZero     /* Get length from command */
1146*042d53a7SEvalZero     len = cmdbuf[sizeof(uint16_t)];
1147*042d53a7SEvalZero 
1148*042d53a7SEvalZero     /* Move past HCI command header */
1149*042d53a7SEvalZero     cmdbuf += BLE_HCI_CMD_HDR_LEN;
1150*042d53a7SEvalZero 
1151*042d53a7SEvalZero     switch (ocf) {
1152*042d53a7SEvalZero     case BLE_HCI_OCF_DISCONNECT_CMD:
1153*042d53a7SEvalZero         if (len == BLE_HCI_DISCONNECT_CMD_LEN) {
1154*042d53a7SEvalZero             rc = ble_ll_conn_hci_disconnect_cmd(cmdbuf);
1155*042d53a7SEvalZero         }
1156*042d53a7SEvalZero         /* Send command status instead of command complete */
1157*042d53a7SEvalZero         rc += (BLE_ERR_MAX + 1);
1158*042d53a7SEvalZero         break;
1159*042d53a7SEvalZero 
1160*042d53a7SEvalZero     case BLE_HCI_OCF_RD_REM_VER_INFO:
1161*042d53a7SEvalZero         if (len == sizeof(uint16_t)) {
1162*042d53a7SEvalZero             rc = ble_ll_conn_hci_rd_rem_ver_cmd(cmdbuf);
1163*042d53a7SEvalZero         }
1164*042d53a7SEvalZero         /* Send command status instead of command complete */
1165*042d53a7SEvalZero         rc += (BLE_ERR_MAX + 1);
1166*042d53a7SEvalZero         break;
1167*042d53a7SEvalZero 
1168*042d53a7SEvalZero     default:
1169*042d53a7SEvalZero         rc = BLE_ERR_UNKNOWN_HCI_CMD;
1170*042d53a7SEvalZero         break;
1171*042d53a7SEvalZero     }
1172*042d53a7SEvalZero 
1173*042d53a7SEvalZero     return rc;
1174*042d53a7SEvalZero }
1175*042d53a7SEvalZero 
1176*042d53a7SEvalZero static int
ble_ll_hci_ctlr_bb_cmd_proc(uint8_t * cmdbuf,uint16_t ocf,uint8_t * rsplen)1177*042d53a7SEvalZero ble_ll_hci_ctlr_bb_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
1178*042d53a7SEvalZero {
1179*042d53a7SEvalZero     int rc;
1180*042d53a7SEvalZero     uint8_t len;
1181*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) == 1)
1182*042d53a7SEvalZero     uint8_t *rspbuf;
1183*042d53a7SEvalZero #endif
1184*042d53a7SEvalZero 
1185*042d53a7SEvalZero     /* Assume error; if all pass rc gets set to 0 */
1186*042d53a7SEvalZero     rc = BLE_ERR_INV_HCI_CMD_PARMS;
1187*042d53a7SEvalZero 
1188*042d53a7SEvalZero     /* Get length from command */
1189*042d53a7SEvalZero     len = cmdbuf[sizeof(uint16_t)];
1190*042d53a7SEvalZero 
1191*042d53a7SEvalZero     /* Move past HCI command header */
1192*042d53a7SEvalZero     cmdbuf += BLE_HCI_CMD_HDR_LEN;
1193*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) == 1)
1194*042d53a7SEvalZero     rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN;
1195*042d53a7SEvalZero #endif
1196*042d53a7SEvalZero 
1197*042d53a7SEvalZero     switch (ocf) {
1198*042d53a7SEvalZero     case BLE_HCI_OCF_CB_SET_EVENT_MASK:
1199*042d53a7SEvalZero         if (len == BLE_HCI_SET_EVENT_MASK_LEN) {
1200*042d53a7SEvalZero             memcpy(g_ble_ll_hci_event_mask, cmdbuf, len);
1201*042d53a7SEvalZero             rc = BLE_ERR_SUCCESS;
1202*042d53a7SEvalZero         }
1203*042d53a7SEvalZero         break;
1204*042d53a7SEvalZero     case BLE_HCI_OCF_CB_RESET:
1205*042d53a7SEvalZero         if (len == 0) {
1206*042d53a7SEvalZero             rc = ble_ll_reset();
1207*042d53a7SEvalZero         }
1208*042d53a7SEvalZero         break;
1209*042d53a7SEvalZero     case BLE_HCI_OCF_CB_SET_EVENT_MASK2:
1210*042d53a7SEvalZero         if (len == BLE_HCI_SET_EVENT_MASK_LEN) {
1211*042d53a7SEvalZero             memcpy(g_ble_ll_hci_event_mask2, cmdbuf, len);
1212*042d53a7SEvalZero             rc = BLE_ERR_SUCCESS;
1213*042d53a7SEvalZero         }
1214*042d53a7SEvalZero         break;
1215*042d53a7SEvalZero #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING) == 1)
1216*042d53a7SEvalZero     case BLE_HCI_OCF_CB_RD_AUTH_PYLD_TMO:
1217*042d53a7SEvalZero         rc = ble_ll_conn_hci_rd_auth_pyld_tmo(cmdbuf, rspbuf, rsplen);
1218*042d53a7SEvalZero         break;
1219*042d53a7SEvalZero     case BLE_HCI_OCF_CB_WR_AUTH_PYLD_TMO:
1220*042d53a7SEvalZero         rc = ble_ll_conn_hci_wr_auth_pyld_tmo(cmdbuf, rspbuf, rsplen);
1221*042d53a7SEvalZero         break;
1222*042d53a7SEvalZero #endif
1223*042d53a7SEvalZero     default:
1224*042d53a7SEvalZero         rc = BLE_ERR_UNKNOWN_HCI_CMD;
1225*042d53a7SEvalZero         break;
1226*042d53a7SEvalZero     }
1227*042d53a7SEvalZero 
1228*042d53a7SEvalZero     return rc;
1229*042d53a7SEvalZero }
1230*042d53a7SEvalZero 
1231*042d53a7SEvalZero static int
ble_ll_hci_info_params_cmd_proc(uint8_t * cmdbuf,uint16_t ocf,uint8_t * rsplen)1232*042d53a7SEvalZero ble_ll_hci_info_params_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
1233*042d53a7SEvalZero {
1234*042d53a7SEvalZero     int rc;
1235*042d53a7SEvalZero     uint8_t len;
1236*042d53a7SEvalZero     uint8_t *rspbuf;
1237*042d53a7SEvalZero 
1238*042d53a7SEvalZero     /* Assume error; if all pass rc gets set to 0 */
1239*042d53a7SEvalZero     rc = BLE_ERR_INV_HCI_CMD_PARMS;
1240*042d53a7SEvalZero 
1241*042d53a7SEvalZero     /* Get length from command */
1242*042d53a7SEvalZero     len = cmdbuf[sizeof(uint16_t)];
1243*042d53a7SEvalZero 
1244*042d53a7SEvalZero     /*
1245*042d53a7SEvalZero      * The command response pointer points into the same buffer as the
1246*042d53a7SEvalZero      * command data itself. That is fine, as each command reads all the data
1247*042d53a7SEvalZero      * before crafting a response.
1248*042d53a7SEvalZero      */
1249*042d53a7SEvalZero     rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN;
1250*042d53a7SEvalZero 
1251*042d53a7SEvalZero     /* Move past HCI command header */
1252*042d53a7SEvalZero     cmdbuf += BLE_HCI_CMD_HDR_LEN;
1253*042d53a7SEvalZero 
1254*042d53a7SEvalZero     switch (ocf) {
1255*042d53a7SEvalZero     case BLE_HCI_OCF_IP_RD_LOCAL_VER:
1256*042d53a7SEvalZero         if (len == 0) {
1257*042d53a7SEvalZero             rc = ble_ll_hci_rd_local_version(rspbuf, rsplen);
1258*042d53a7SEvalZero         }
1259*042d53a7SEvalZero         break;
1260*042d53a7SEvalZero     case BLE_HCI_OCF_IP_RD_LOC_SUPP_CMD:
1261*042d53a7SEvalZero         if (len == 0) {
1262*042d53a7SEvalZero             rc = ble_ll_hci_rd_local_supp_cmd(rspbuf, rsplen);
1263*042d53a7SEvalZero         }
1264*042d53a7SEvalZero         break;
1265*042d53a7SEvalZero     case BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT:
1266*042d53a7SEvalZero         if (len == 0) {
1267*042d53a7SEvalZero             rc = ble_ll_hci_rd_local_supp_feat(rspbuf, rsplen);
1268*042d53a7SEvalZero         }
1269*042d53a7SEvalZero         break;
1270*042d53a7SEvalZero     case BLE_HCI_OCF_IP_RD_BD_ADDR:
1271*042d53a7SEvalZero         if (len == 0) {
1272*042d53a7SEvalZero             rc = ble_ll_hci_rd_bd_addr(rspbuf, rsplen);
1273*042d53a7SEvalZero         }
1274*042d53a7SEvalZero         break;
1275*042d53a7SEvalZero     default:
1276*042d53a7SEvalZero         rc = BLE_ERR_UNKNOWN_HCI_CMD;
1277*042d53a7SEvalZero         break;
1278*042d53a7SEvalZero     }
1279*042d53a7SEvalZero 
1280*042d53a7SEvalZero     return rc;
1281*042d53a7SEvalZero }
1282*042d53a7SEvalZero 
1283*042d53a7SEvalZero static int
ble_ll_hci_status_params_cmd_proc(uint8_t * cmdbuf,uint16_t ocf,uint8_t * rsplen)1284*042d53a7SEvalZero ble_ll_hci_status_params_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
1285*042d53a7SEvalZero {
1286*042d53a7SEvalZero     int rc;
1287*042d53a7SEvalZero     uint8_t len;
1288*042d53a7SEvalZero     uint8_t *rspbuf;
1289*042d53a7SEvalZero 
1290*042d53a7SEvalZero     /* Assume error; if all pass rc gets set to 0 */
1291*042d53a7SEvalZero     rc = BLE_ERR_INV_HCI_CMD_PARMS;
1292*042d53a7SEvalZero 
1293*042d53a7SEvalZero     /* Get length from command */
1294*042d53a7SEvalZero     len = cmdbuf[sizeof(uint16_t)];
1295*042d53a7SEvalZero 
1296*042d53a7SEvalZero     /*
1297*042d53a7SEvalZero      * The command response pointer points into the same buffer as the
1298*042d53a7SEvalZero      * command data itself. That is fine, as each command reads all the data
1299*042d53a7SEvalZero      * before crafting a response.
1300*042d53a7SEvalZero      */
1301*042d53a7SEvalZero     rspbuf = cmdbuf + BLE_HCI_EVENT_CMD_COMPLETE_MIN_LEN;
1302*042d53a7SEvalZero 
1303*042d53a7SEvalZero     /* Move past HCI command header */
1304*042d53a7SEvalZero     cmdbuf += BLE_HCI_CMD_HDR_LEN;
1305*042d53a7SEvalZero 
1306*042d53a7SEvalZero     switch (ocf) {
1307*042d53a7SEvalZero     case BLE_HCI_OCF_RD_RSSI:
1308*042d53a7SEvalZero         if (len == sizeof(uint16_t)) {
1309*042d53a7SEvalZero             rc = ble_ll_conn_hci_rd_rssi(cmdbuf, rspbuf, rsplen);
1310*042d53a7SEvalZero         }
1311*042d53a7SEvalZero         break;
1312*042d53a7SEvalZero     default:
1313*042d53a7SEvalZero         rc = BLE_ERR_UNKNOWN_HCI_CMD;
1314*042d53a7SEvalZero         break;
1315*042d53a7SEvalZero     }
1316*042d53a7SEvalZero 
1317*042d53a7SEvalZero     return rc;
1318*042d53a7SEvalZero }
1319*042d53a7SEvalZero 
1320*042d53a7SEvalZero /**
1321*042d53a7SEvalZero  * Called to process an HCI command from the host.
1322*042d53a7SEvalZero  *
1323*042d53a7SEvalZero  * @param ev Pointer to os event containing a pointer to command buffer
1324*042d53a7SEvalZero  */
1325*042d53a7SEvalZero static void
ble_ll_hci_cmd_proc(struct ble_npl_event * ev)1326*042d53a7SEvalZero ble_ll_hci_cmd_proc(struct ble_npl_event *ev)
1327*042d53a7SEvalZero {
1328*042d53a7SEvalZero     int rc;
1329*042d53a7SEvalZero     uint8_t ogf;
1330*042d53a7SEvalZero     uint8_t rsplen;
1331*042d53a7SEvalZero     uint8_t *cmdbuf;
1332*042d53a7SEvalZero     uint16_t opcode;
1333*042d53a7SEvalZero     uint16_t ocf;
1334*042d53a7SEvalZero     ble_ll_hci_post_cmd_complete_cb post_cb = NULL;
1335*042d53a7SEvalZero 
1336*042d53a7SEvalZero     /* The command buffer is the event argument */
1337*042d53a7SEvalZero     cmdbuf = (uint8_t *)ble_npl_event_get_arg(ev);
1338*042d53a7SEvalZero     BLE_LL_ASSERT(cmdbuf != NULL);
1339*042d53a7SEvalZero 
1340*042d53a7SEvalZero     /* Get the opcode from the command buffer */
1341*042d53a7SEvalZero     opcode = get_le16(cmdbuf);
1342*042d53a7SEvalZero     ocf = BLE_HCI_OCF(opcode);
1343*042d53a7SEvalZero     ogf = BLE_HCI_OGF(opcode);
1344*042d53a7SEvalZero 
1345*042d53a7SEvalZero     /* Assume response length is zero */
1346*042d53a7SEvalZero     rsplen = 0;
1347*042d53a7SEvalZero 
1348*042d53a7SEvalZero     switch (ogf) {
1349*042d53a7SEvalZero     case BLE_HCI_OGF_LINK_CTRL:
1350*042d53a7SEvalZero         rc = ble_ll_hci_link_ctrl_cmd_proc(cmdbuf, ocf, &rsplen);
1351*042d53a7SEvalZero         break;
1352*042d53a7SEvalZero     case BLE_HCI_OGF_CTLR_BASEBAND:
1353*042d53a7SEvalZero         rc = ble_ll_hci_ctlr_bb_cmd_proc(cmdbuf, ocf, &rsplen);
1354*042d53a7SEvalZero         break;
1355*042d53a7SEvalZero     case BLE_HCI_OGF_INFO_PARAMS:
1356*042d53a7SEvalZero         rc = ble_ll_hci_info_params_cmd_proc(cmdbuf, ocf, &rsplen);
1357*042d53a7SEvalZero         break;
1358*042d53a7SEvalZero     case BLE_HCI_OGF_STATUS_PARAMS:
1359*042d53a7SEvalZero         rc = ble_ll_hci_status_params_cmd_proc(cmdbuf, ocf, &rsplen);
1360*042d53a7SEvalZero         break;
1361*042d53a7SEvalZero     case BLE_HCI_OGF_LE:
1362*042d53a7SEvalZero         rc = ble_ll_hci_le_cmd_proc(cmdbuf, ocf, &rsplen, &post_cb);
1363*042d53a7SEvalZero         break;
1364*042d53a7SEvalZero     default:
1365*042d53a7SEvalZero         /* XXX: Need to support other OGF. For now, return unsupported */
1366*042d53a7SEvalZero         rc = BLE_ERR_UNKNOWN_HCI_CMD;
1367*042d53a7SEvalZero         break;
1368*042d53a7SEvalZero     }
1369*042d53a7SEvalZero 
1370*042d53a7SEvalZero     /* If no response is generated, we free the buffers */
1371*042d53a7SEvalZero     BLE_LL_ASSERT(rc >= 0);
1372*042d53a7SEvalZero     if (rc <= BLE_ERR_MAX) {
1373*042d53a7SEvalZero         /* Create a command complete event with status from command */
1374*042d53a7SEvalZero         cmdbuf[0] = BLE_HCI_EVCODE_COMMAND_COMPLETE;
1375*042d53a7SEvalZero         cmdbuf[1] = 4 + rsplen;
1376*042d53a7SEvalZero         cmdbuf[2] = ble_ll_hci_get_num_cmd_pkts();
1377*042d53a7SEvalZero         put_le16(cmdbuf + 3, opcode);
1378*042d53a7SEvalZero         cmdbuf[5] = (uint8_t)rc;
1379*042d53a7SEvalZero     } else {
1380*042d53a7SEvalZero         /* Create a command status event */
1381*042d53a7SEvalZero         rc -= (BLE_ERR_MAX + 1);
1382*042d53a7SEvalZero         cmdbuf[0] = BLE_HCI_EVCODE_COMMAND_STATUS;
1383*042d53a7SEvalZero         cmdbuf[1] = 4;
1384*042d53a7SEvalZero         cmdbuf[2] = (uint8_t)rc;
1385*042d53a7SEvalZero         cmdbuf[3] = ble_ll_hci_get_num_cmd_pkts();
1386*042d53a7SEvalZero         put_le16(cmdbuf + 4, opcode);
1387*042d53a7SEvalZero     }
1388*042d53a7SEvalZero 
1389*042d53a7SEvalZero     /* Count commands and those in error */
1390*042d53a7SEvalZero     if (rc) {
1391*042d53a7SEvalZero         STATS_INC(ble_ll_stats, hci_cmd_errs);
1392*042d53a7SEvalZero     } else {
1393*042d53a7SEvalZero         STATS_INC(ble_ll_stats, hci_cmds);
1394*042d53a7SEvalZero     }
1395*042d53a7SEvalZero 
1396*042d53a7SEvalZero     /* Send the event (events cannot be masked) */
1397*042d53a7SEvalZero     ble_ll_hci_event_send(cmdbuf);
1398*042d53a7SEvalZero 
1399*042d53a7SEvalZero     /* Call post callback if set by command handler */
1400*042d53a7SEvalZero     if (post_cb) {
1401*042d53a7SEvalZero         post_cb();
1402*042d53a7SEvalZero     }
1403*042d53a7SEvalZero }
1404*042d53a7SEvalZero 
1405*042d53a7SEvalZero /**
1406*042d53a7SEvalZero  * Sends an HCI command to the controller.  On success, the supplied buffer is
1407*042d53a7SEvalZero  * relinquished to the controller task.  On failure, the caller must free the
1408*042d53a7SEvalZero  * buffer.
1409*042d53a7SEvalZero  *
1410*042d53a7SEvalZero  * @param cmd                   A flat buffer containing the HCI command to
1411*042d53a7SEvalZero  *                                  send.
1412*042d53a7SEvalZero  *
1413*042d53a7SEvalZero  * @return                      0 on success;
1414*042d53a7SEvalZero  *                              BLE_ERR_MEM_CAPACITY on HCI buffer exhaustion.
1415*042d53a7SEvalZero  */
1416*042d53a7SEvalZero int
ble_ll_hci_cmd_rx(uint8_t * cmd,void * arg)1417*042d53a7SEvalZero ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg)
1418*042d53a7SEvalZero {
1419*042d53a7SEvalZero     struct ble_npl_event *ev;
1420*042d53a7SEvalZero 
1421*042d53a7SEvalZero     /* Get an event structure off the queue */
1422*042d53a7SEvalZero     ev = &g_ble_ll_hci_cmd_ev;
1423*042d53a7SEvalZero     if (ble_npl_event_is_queued(ev)) {
1424*042d53a7SEvalZero         return BLE_ERR_MEM_CAPACITY;
1425*042d53a7SEvalZero     }
1426*042d53a7SEvalZero 
1427*042d53a7SEvalZero     /* Fill out the event and post to Link Layer */
1428*042d53a7SEvalZero     ble_npl_event_set_arg(ev, cmd);
1429*042d53a7SEvalZero     ble_npl_eventq_put(&g_ble_ll_data.ll_evq, ev);
1430*042d53a7SEvalZero 
1431*042d53a7SEvalZero     return 0;
1432*042d53a7SEvalZero }
1433*042d53a7SEvalZero 
1434*042d53a7SEvalZero /* Send ACL data from host to contoller */
1435*042d53a7SEvalZero int
ble_ll_hci_acl_rx(struct os_mbuf * om,void * arg)1436*042d53a7SEvalZero ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg)
1437*042d53a7SEvalZero {
1438*042d53a7SEvalZero     ble_ll_acl_data_in(om);
1439*042d53a7SEvalZero     return 0;
1440*042d53a7SEvalZero }
1441*042d53a7SEvalZero 
1442*042d53a7SEvalZero /**
1443*042d53a7SEvalZero  * Initalize the LL HCI.
1444*042d53a7SEvalZero  *
1445*042d53a7SEvalZero  * NOTE: This function is called by the HCI RESET command so if any code
1446*042d53a7SEvalZero  * is added here it must be OK to be executed when the reset command is used.
1447*042d53a7SEvalZero  */
1448*042d53a7SEvalZero void
ble_ll_hci_init(void)1449*042d53a7SEvalZero ble_ll_hci_init(void)
1450*042d53a7SEvalZero {
1451*042d53a7SEvalZero     /* Set event callback for command processing */
1452*042d53a7SEvalZero     ble_npl_event_init(&g_ble_ll_hci_cmd_ev, ble_ll_hci_cmd_proc, NULL);
1453*042d53a7SEvalZero 
1454*042d53a7SEvalZero     /* Set defaults for LE events: Vol 2 Part E 7.8.1 */
1455*042d53a7SEvalZero     g_ble_ll_hci_le_event_mask[0] = 0x1f;
1456*042d53a7SEvalZero 
1457*042d53a7SEvalZero     /* Set defaults for controller/baseband events: Vol 2 Part E 7.3.1 */
1458*042d53a7SEvalZero     g_ble_ll_hci_event_mask[0] = 0xff;
1459*042d53a7SEvalZero     g_ble_ll_hci_event_mask[1] = 0xff;
1460*042d53a7SEvalZero     g_ble_ll_hci_event_mask[2] = 0xff;
1461*042d53a7SEvalZero     g_ble_ll_hci_event_mask[3] = 0xff;
1462*042d53a7SEvalZero     g_ble_ll_hci_event_mask[4] = 0xff;
1463*042d53a7SEvalZero     g_ble_ll_hci_event_mask[5] = 0x1f;
1464*042d53a7SEvalZero 
1465*042d53a7SEvalZero     /* Set page 2 to 0 */
1466*042d53a7SEvalZero     memset(g_ble_ll_hci_event_mask2, 0, BLE_HCI_SET_EVENT_MASK_LEN);
1467*042d53a7SEvalZero 
1468*042d53a7SEvalZero #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
1469*042d53a7SEvalZero     /* after reset both legacy and extended advertising commands are allowed */
1470*042d53a7SEvalZero     hci_adv_mode = ADV_MODE_ANY;
1471*042d53a7SEvalZero #endif
1472*042d53a7SEvalZero }
1473