xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_hs_startup.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <stddef.h>
21 #include <string.h>
22 #include "host/ble_hs.h"
23 #include "host/ble_hs_hci.h"
24 #include "ble_hs_priv.h"
25 
26 #if !MYNEWT_VAL(BLE_DEVICE)
27 static int
ble_hs_startup_read_sup_f_tx(void)28 ble_hs_startup_read_sup_f_tx(void)
29 {
30     uint8_t ack_params[BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN];
31     uint8_t ack_params_len;
32     int rc;
33 
34     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
35                                       BLE_HCI_OCF_IP_RD_LOC_SUPP_FEAT),
36                            NULL,0, ack_params, sizeof ack_params,
37                            &ack_params_len);
38     if (rc != 0) {
39         return rc;
40     }
41 
42     if (ack_params_len != BLE_HCI_RD_LOC_SUPP_FEAT_RSPLEN) {
43         return BLE_HS_ECONTROLLER;
44     }
45 
46     /* for now we don't use it outside of init sequence so check this here
47      * LE Supported (Controller) byte 4, bit 6
48      */
49     if (!(ack_params[4] & 0x60)) {
50         BLE_HS_LOG(ERROR, "Controller doesn't support LE\n");
51         return BLE_HS_ECONTROLLER;
52     }
53 
54     return 0;
55 }
56 #endif
57 
58 static int
ble_hs_startup_read_local_ver_tx(void)59 ble_hs_startup_read_local_ver_tx(void)
60 {
61     uint8_t ack_params[BLE_HCI_RD_LOC_VER_INFO_RSPLEN];
62     uint8_t ack_params_len;
63     uint8_t hci_version;
64     int rc;
65 
66     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
67                                       BLE_HCI_OCF_IP_RD_LOCAL_VER),
68                            NULL,0, ack_params, sizeof ack_params,
69                            &ack_params_len);
70     if (rc != 0) {
71         return rc;
72     }
73 
74     if (ack_params_len != BLE_HCI_RD_LOC_VER_INFO_RSPLEN) {
75         return BLE_HS_ECONTROLLER;
76     }
77 
78     /* For now we are interested only in HCI Version */
79     hci_version = ack_params[0];
80     ble_hs_hci_set_hci_version(hci_version);
81 
82     return 0;
83 }
84 
85 static int
ble_hs_startup_le_read_sup_f_tx(void)86 ble_hs_startup_le_read_sup_f_tx(void)
87 {
88     uint8_t ack_params[BLE_HCI_RD_LE_LOC_SUPP_FEAT_RSPLEN];
89     uint8_t ack_params_len;
90     uint32_t feat;
91     int rc;
92 
93     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
94                                       BLE_HCI_OCF_LE_RD_LOC_SUPP_FEAT),
95                            NULL,0, ack_params, sizeof ack_params,
96                            &ack_params_len);
97     if (rc != 0) {
98         return rc;
99     }
100 
101     if (ack_params_len != BLE_HCI_RD_LE_LOC_SUPP_FEAT_RSPLEN) {
102         return BLE_HS_ECONTROLLER;
103     }
104 
105     /* For now 32-bits of features is enough */
106     feat = get_le32(ack_params);
107     ble_hs_hci_set_le_supported_feat(feat);
108 
109     return 0;
110 }
111 
112 static int
ble_hs_startup_le_read_buf_sz_tx(uint16_t * out_pktlen,uint8_t * out_max_pkts)113 ble_hs_startup_le_read_buf_sz_tx(uint16_t *out_pktlen, uint8_t *out_max_pkts)
114 {
115     uint8_t ack_params[BLE_HCI_RD_BUF_SIZE_RSPLEN];
116     uint8_t ack_params_len;
117     int rc;
118 
119     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
120                                       BLE_HCI_OCF_LE_RD_BUF_SIZE), NULL, 0,
121                            ack_params, sizeof ack_params, &ack_params_len);
122     if (rc != 0) {
123         return rc;
124     }
125 
126     if (ack_params_len != BLE_HCI_RD_BUF_SIZE_RSPLEN) {
127         return BLE_HS_ECONTROLLER;
128     }
129 
130     *out_pktlen = get_le16(ack_params + 0);
131     *out_max_pkts = ack_params[2];
132 
133     return 0;
134 }
135 
136 static int
ble_hs_startup_read_buf_sz_tx(uint16_t * out_pktlen,uint16_t * out_max_pkts)137 ble_hs_startup_read_buf_sz_tx(uint16_t *out_pktlen, uint16_t *out_max_pkts)
138 {
139     uint8_t ack_params[BLE_HCI_IP_RD_BUF_SIZE_RSPLEN];
140     uint8_t ack_params_len;
141     int rc;
142 
143     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
144                                       BLE_HCI_OCF_IP_RD_BUF_SIZE), NULL, 0,
145                            ack_params, sizeof ack_params, &ack_params_len);
146     if (rc != 0) {
147         return rc;
148     }
149 
150     if (ack_params_len != BLE_HCI_IP_RD_BUF_SIZE_RSPLEN) {
151         return BLE_HS_ECONTROLLER;
152     }
153 
154     *out_pktlen = get_le16(ack_params + 0);
155     *out_max_pkts = get_le16(ack_params + 3);
156 
157     return 0;
158 }
159 
160 static int
ble_hs_startup_read_buf_sz(void)161 ble_hs_startup_read_buf_sz(void)
162 {
163     uint16_t le_pktlen = 0;
164     uint16_t max_pkts = 0;
165     uint16_t pktlen = 0;
166     uint8_t le_max_pkts = 0;
167     int rc;
168 
169     rc = ble_hs_startup_le_read_buf_sz_tx(&le_pktlen, &le_max_pkts);
170     if (rc != 0) {
171         return rc;
172     }
173 
174     if (le_pktlen != 0) {
175         pktlen = le_pktlen;
176         max_pkts = le_max_pkts;
177     } else {
178         rc = ble_hs_startup_read_buf_sz_tx(&pktlen, &max_pkts);
179         if (rc != 0) {
180             return rc;
181         }
182     }
183 
184     rc = ble_hs_hci_set_buf_sz(pktlen, max_pkts);
185     if (rc != 0) {
186         return rc;
187     }
188 
189     return 0;
190 }
191 
192 static int
ble_hs_startup_read_bd_addr(void)193 ble_hs_startup_read_bd_addr(void)
194 {
195     uint8_t ack_params[BLE_HCI_IP_RD_BD_ADDR_ACK_PARAM_LEN];
196     uint8_t ack_params_len;
197     int rc;
198 
199     rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_INFO_PARAMS,
200                                       BLE_HCI_OCF_IP_RD_BD_ADDR),
201                            NULL, 0, ack_params, sizeof ack_params,
202                            &ack_params_len);
203     if (rc != 0) {
204         return rc;
205     }
206 
207     if (ack_params_len != sizeof ack_params) {
208         return BLE_HS_ECONTROLLER;
209     }
210 
211     ble_hs_id_set_pub(ack_params);
212     return 0;
213 }
214 
215 static int
ble_hs_startup_le_set_evmask_tx(void)216 ble_hs_startup_le_set_evmask_tx(void)
217 {
218     uint8_t buf[BLE_HCI_SET_LE_EVENT_MASK_LEN];
219     uint8_t version;
220     uint64_t mask;
221     int rc;
222 
223     version = ble_hs_hci_get_hci_version();
224 
225     /* TODO should we also check for supported commands when setting this? */
226 
227     /**
228      * Enable the following LE events:
229      *     0x0000000000000001 LE Connection Complete Event
230      *     0x0000000000000002 LE Advertising Report Event
231      *     0x0000000000000004 LE Connection Update Complete Event
232      *     0x0000000000000008 LE Read Remote Used Features Complete Event
233      *     0x0000000000000010 LE Long Term Key Request Event
234      */
235     mask = 0x000000000000001f;
236 
237     if (version >= BLE_HCI_VER_BCS_4_1) {
238         /**
239          * Enable the following LE events:
240          *   0x0000000000000020 LE Remote Connection Parameter Request Event */
241         mask |= 0x0000000000000020;
242     }
243 
244     if (version >= BLE_HCI_VER_BCS_4_2) {
245         /**
246          * Enable the following LE events:
247          *   0x0000000000000040 LE Data Length Change Event
248          *   0x0000000000000200 LE Enhanced Connection Complete Event
249          *   0x0000000000000400 LE Directed Advertising Report Event
250          */
251         mask |= 0x0000000000000640;
252     }
253 
254     if (version >= BLE_HCI_VER_BCS_5_0) {
255         /**
256          * Enable the following LE events:
257          *   0x0000000000000800 LE PHY Update Complete Event
258          *   0x0000000000001000 LE Extended Advertising Report Event
259          *   0x0000000000010000 LE Extended Scan Timeout Event
260          *   0x0000000000020000 LE Extended Advertising Set Terminated Event
261          *   0x0000000000040000 LE Scan Request Received Event
262          *   0x0000000000080000 LE Channel Selection Algorithm Event
263          */
264         mask |= 0x00000000000f1800;
265     }
266 
267     ble_hs_hci_cmd_build_le_set_event_mask(mask, buf, sizeof buf);
268     rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
269                                                 BLE_HCI_OCF_LE_SET_EVENT_MASK),
270                                      buf, sizeof(buf));
271     if (rc != 0) {
272         return rc;
273     }
274 
275     return 0;
276 }
277 
278 static int
ble_hs_startup_set_evmask_tx(void)279 ble_hs_startup_set_evmask_tx(void)
280 {
281     uint8_t buf[BLE_HCI_SET_EVENT_MASK_LEN];
282     uint8_t version;
283     int rc;
284 
285     version = ble_hs_hci_get_hci_version();
286 
287     /**
288      * Enable the following events:
289      *     0x0000000000000010 Disconnection Complete Event
290      *     0x0000000000000080 Encryption Change Event
291      *     0x0000000000008000 Hardware Error Event
292      *     0x0000000002000000 Data Buffer Overflow Event
293      *     0x0000800000000000 Encryption Key Refresh Complete Event
294      *     0x2000000000000000 LE Meta-Event
295      */
296     ble_hs_hci_cmd_build_set_event_mask(0x2000800002008090, buf, sizeof buf);
297     rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
298                                                 BLE_HCI_OCF_CB_SET_EVENT_MASK),
299                                      buf, sizeof(buf));
300     if (rc != 0) {
301         return rc;
302     }
303 
304     if (version >= BLE_HCI_VER_BCS_4_1) {
305         /**
306          * Enable the following events:
307          *     0x0000000000800000 Authenticated Payload Timeout Event
308          */
309         ble_hs_hci_cmd_build_set_event_mask2(0x0000000000800000, buf, sizeof buf);
310         rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
311                                                     BLE_HCI_OCF_CB_SET_EVENT_MASK2),
312                                          buf, sizeof(buf));
313         if (rc != 0) {
314             return rc;
315         }
316     }
317 
318     return 0;
319 }
320 
321 static int
ble_hs_startup_reset_tx(void)322 ble_hs_startup_reset_tx(void)
323 {
324     int rc;
325 
326     rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_CTLR_BASEBAND,
327                                                 BLE_HCI_OCF_CB_RESET),
328                                      NULL, 0);
329     if (rc != 0) {
330         return rc;
331     }
332 
333     return 0;
334 }
335 
336 int
ble_hs_startup_go(void)337 ble_hs_startup_go(void)
338 {
339     int rc;
340 
341     rc = ble_hs_startup_reset_tx();
342     if (rc != 0) {
343         return rc;
344     }
345 
346     rc = ble_hs_startup_read_local_ver_tx();
347     if (rc != 0) {
348         return rc;
349     }
350 
351     /* XXX: Read local supported commands. */
352 
353     /* we need to check this only if using external controller */
354 #if !MYNEWT_VAL(BLE_DEVICE)
355     if (ble_hs_hci_get_hci_version() < BLE_HCI_VER_BCS_4_0) {
356         BLE_HS_LOG(ERROR, "Required controller version is 4.0 (6)\n");
357         return BLE_HS_ECONTROLLER;
358     }
359 
360     rc = ble_hs_startup_read_sup_f_tx();
361     if (rc != 0) {
362         return rc;
363     }
364 #endif
365 
366     rc = ble_hs_startup_set_evmask_tx();
367     if (rc != 0) {
368         return rc;
369     }
370 
371     rc = ble_hs_startup_le_set_evmask_tx();
372     if (rc != 0) {
373         return rc;
374     }
375 
376     rc = ble_hs_startup_read_buf_sz();
377     if (rc != 0) {
378         return rc;
379     }
380 
381     rc = ble_hs_startup_le_read_sup_f_tx();
382     if (rc != 0) {
383         return rc;
384     }
385 
386     rc = ble_hs_startup_read_bd_addr();
387     if (rc != 0) {
388         return rc;
389     }
390 
391     ble_hs_pvcy_set_our_irk(NULL);
392 
393     /* If flow control is enabled, configure the controller to use it. */
394     ble_hs_flow_startup();
395 
396     return 0;
397 }
398