1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <stdint.h>
21 #include <assert.h>
22 #include <string.h>
23 #include "syscfg/syscfg.h"
24 #include "os/os.h"
25 #include "ble/xcvr.h"
26 #include "nimble/ble.h"
27 #include "nimble/nimble_opt.h"
28 #include "nrfx.h"
29 #include "controller/ble_hw.h"
30 #include "mcu/cmsis_nvic.h"
31
32 /* Total number of resolving list elements */
33 #define BLE_HW_RESOLV_LIST_SIZE (16)
34
35 /* We use this to keep track of which entries are set to valid addresses */
36 static uint8_t g_ble_hw_whitelist_mask;
37
38 /* Random number generator isr callback */
39 ble_rng_isr_cb_t g_ble_rng_isr_cb;
40
41 /* If LL privacy is enabled, allocate memory for AAR */
42 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
43
44 /* The NRF51 supports up to 16 IRK entries */
45 #if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
46 #define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
47 #else
48 #define NRF_IRK_LIST_ENTRIES (16)
49 #endif
50
51 /* NOTE: each entry is 16 bytes long. */
52 uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
53
54 /* Current number of IRK entries */
55 uint8_t g_nrf_num_irks;
56
57 #endif
58
59 /* Returns public device address or -1 if not present */
60 int
ble_hw_get_public_addr(ble_addr_t * addr)61 ble_hw_get_public_addr(ble_addr_t *addr)
62 {
63 int rc;
64 uint32_t addr_high;
65 uint32_t addr_low;
66
67 /* Does FICR have a public address */
68 rc = -1;
69 if ((NRF_FICR->DEVICEADDRTYPE & 1) == 0) {
70 addr_low = NRF_FICR->DEVICEADDR[0];
71 addr_high = NRF_FICR->DEVICEADDR[1];
72 rc = 0;
73 } else {
74 /* See if programmed in UICR. Upper 16 bits must all be zero */
75 addr_high = NRF_UICR->CUSTOMER[1];
76 if (addr_high < 65536) {
77 addr_low = NRF_UICR->CUSTOMER[0];
78 rc = 0;
79 }
80 }
81
82 if (!rc) {
83 /* Copy into device address. We can do this because we know platform */
84 memcpy(addr->val, &addr_low, 4);
85 memcpy(&addr->val[4], &addr_high, 2);
86 addr->type = BLE_ADDR_PUBLIC;
87 }
88
89 return rc;
90 }
91
92 /* Returns random static address or -1 if not present */
93 int
ble_hw_get_static_addr(ble_addr_t * addr)94 ble_hw_get_static_addr(ble_addr_t *addr)
95 {
96 int rc;
97
98 if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) {
99 memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4);
100 memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2);
101 addr->val[5] |= 0xc0;
102 addr->type = BLE_ADDR_RANDOM;
103 rc = 0;
104 } else {
105 rc = -1;
106 }
107
108 return rc;
109 }
110
111 /**
112 * Clear the whitelist
113 *
114 * @return int
115 */
116 void
ble_hw_whitelist_clear(void)117 ble_hw_whitelist_clear(void)
118 {
119 NRF_RADIO->DACNF = 0;
120 g_ble_hw_whitelist_mask = 0;
121 }
122
123 /**
124 * Add a device to the hw whitelist
125 *
126 * @param addr
127 * @param addr_type
128 *
129 * @return int 0: success, BLE error code otherwise
130 */
131 int
ble_hw_whitelist_add(uint8_t * addr,uint8_t addr_type)132 ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
133 {
134 int i;
135 uint32_t mask;
136
137 /* Find first ununsed device address match element */
138 mask = 0x01;
139 for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
140 if ((mask & g_ble_hw_whitelist_mask) == 0) {
141 NRF_RADIO->DAB[i] = get_le32(addr);
142 NRF_RADIO->DAP[i] = get_le16(addr + 4);
143 if (addr_type == BLE_ADDR_RANDOM) {
144 NRF_RADIO->DACNF |= (mask << 8);
145 }
146 g_ble_hw_whitelist_mask |= mask;
147 return BLE_ERR_SUCCESS;
148 }
149 mask <<= 1;
150 }
151
152 return BLE_ERR_MEM_CAPACITY;
153 }
154
155 /**
156 * Remove a device from the hw whitelist
157 *
158 * @param addr
159 * @param addr_type
160 *
161 */
162 void
ble_hw_whitelist_rmv(uint8_t * addr,uint8_t addr_type)163 ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
164 {
165 int i;
166 uint8_t cfg_addr;
167 uint16_t dap;
168 uint16_t txadd;
169 uint32_t dab;
170 uint32_t mask;
171
172 /* Find first ununsed device address match element */
173 dab = get_le32(addr);
174 dap = get_le16(addr + 4);
175 txadd = NRF_RADIO->DACNF >> 8;
176 mask = 0x01;
177 for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
178 if (mask & g_ble_hw_whitelist_mask) {
179 if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) {
180 cfg_addr = txadd & mask;
181 if (addr_type == BLE_ADDR_RANDOM) {
182 if (cfg_addr != 0) {
183 break;
184 }
185 } else {
186 if (cfg_addr == 0) {
187 break;
188 }
189 }
190 }
191 }
192 mask <<= 1;
193 }
194
195 if (i < BLE_HW_WHITE_LIST_SIZE) {
196 g_ble_hw_whitelist_mask &= ~mask;
197 NRF_RADIO->DACNF &= ~mask;
198 }
199 }
200
201 /**
202 * Returns the size of the whitelist in HW
203 *
204 * @return int Number of devices allowed in whitelist
205 */
206 uint8_t
ble_hw_whitelist_size(void)207 ble_hw_whitelist_size(void)
208 {
209 return BLE_HW_WHITE_LIST_SIZE;
210 }
211
212 /**
213 * Enable the whitelisted devices
214 */
215 void
ble_hw_whitelist_enable(void)216 ble_hw_whitelist_enable(void)
217 {
218 /* Enable the configured device addresses */
219 NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask;
220 }
221
222 /**
223 * Disables the whitelisted devices
224 */
225 void
ble_hw_whitelist_disable(void)226 ble_hw_whitelist_disable(void)
227 {
228 /* Disable all whitelist devices */
229 NRF_RADIO->DACNF &= 0x0000ff00;
230 }
231
232 /**
233 * Boolean function which returns true ('1') if there is a match on the
234 * whitelist.
235 *
236 * @return int
237 */
238 int
ble_hw_whitelist_match(void)239 ble_hw_whitelist_match(void)
240 {
241 return (int)NRF_RADIO->EVENTS_DEVMATCH;
242 }
243
244 /* Encrypt data */
245 int
ble_hw_encrypt_block(struct ble_encryption_block * ecb)246 ble_hw_encrypt_block(struct ble_encryption_block *ecb)
247 {
248 int rc;
249 uint32_t end;
250 uint32_t err;
251
252 /* Stop ECB */
253 NRF_ECB->TASKS_STOPECB = 1;
254 /* XXX: does task stop clear these counters? Anyway to do this quicker? */
255 NRF_ECB->EVENTS_ENDECB = 0;
256 NRF_ECB->EVENTS_ERRORECB = 0;
257 NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
258
259 /* Start ECB */
260 NRF_ECB->TASKS_STARTECB = 1;
261
262 /* Wait till error or done */
263 rc = 0;
264 while (1) {
265 end = NRF_ECB->EVENTS_ENDECB;
266 err = NRF_ECB->EVENTS_ERRORECB;
267 if (end || err) {
268 if (err) {
269 rc = -1;
270 }
271 break;
272 }
273 }
274
275 return rc;
276 }
277
278 /**
279 * Random number generator ISR.
280 */
281 static void
ble_rng_isr(void)282 ble_rng_isr(void)
283 {
284 uint8_t rnum;
285
286 os_trace_isr_enter();
287
288 /* No callback? Clear and disable interrupts */
289 if (g_ble_rng_isr_cb == NULL) {
290 NRF_RNG->INTENCLR = 1;
291 NRF_RNG->EVENTS_VALRDY = 0;
292 (void)NRF_RNG->SHORTS;
293 os_trace_isr_exit();
294 return;
295 }
296
297 /* If there is a value ready grab it */
298 if (NRF_RNG->EVENTS_VALRDY) {
299 NRF_RNG->EVENTS_VALRDY = 0;
300 rnum = (uint8_t)NRF_RNG->VALUE;
301 (*g_ble_rng_isr_cb)(rnum);
302 }
303
304 os_trace_isr_exit();
305 }
306
307 /**
308 * Initialize the random number generator
309 *
310 * @param cb
311 * @param bias
312 *
313 * @return int
314 */
315 int
ble_hw_rng_init(ble_rng_isr_cb_t cb,int bias)316 ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
317 {
318 /* Set bias */
319 if (bias) {
320 NRF_RNG->CONFIG = 1;
321 } else {
322 NRF_RNG->CONFIG = 0;
323 }
324
325 /* If we were passed a function pointer we need to enable the interrupt */
326 if (cb != NULL) {
327 NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
328 NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
329 NVIC_EnableIRQ(RNG_IRQn);
330 g_ble_rng_isr_cb = cb;
331 }
332
333 return 0;
334 }
335
336 /**
337 * Start the random number generator
338 *
339 * @return int
340 */
341 int
ble_hw_rng_start(void)342 ble_hw_rng_start(void)
343 {
344 os_sr_t sr;
345
346 /* No need for interrupt if there is no callback */
347 OS_ENTER_CRITICAL(sr);
348 NRF_RNG->EVENTS_VALRDY = 0;
349 if (g_ble_rng_isr_cb) {
350 NRF_RNG->INTENSET = 1;
351 }
352 NRF_RNG->TASKS_START = 1;
353 OS_EXIT_CRITICAL(sr);
354
355 return 0;
356 }
357
358 /**
359 * Stop the random generator
360 *
361 * @return int
362 */
363 int
ble_hw_rng_stop(void)364 ble_hw_rng_stop(void)
365 {
366 os_sr_t sr;
367
368 /* No need for interrupt if there is no callback */
369 OS_ENTER_CRITICAL(sr);
370 NRF_RNG->INTENCLR = 1;
371 NRF_RNG->TASKS_STOP = 1;
372 NRF_RNG->EVENTS_VALRDY = 0;
373 OS_EXIT_CRITICAL(sr);
374
375 return 0;
376 }
377
378 /**
379 * Read the random number generator.
380 *
381 * @return uint8_t
382 */
383 uint8_t
ble_hw_rng_read(void)384 ble_hw_rng_read(void)
385 {
386 uint8_t rnum;
387
388 /* Wait for a sample */
389 while (NRF_RNG->EVENTS_VALRDY == 0) {
390 }
391
392 NRF_RNG->EVENTS_VALRDY = 0;
393 rnum = (uint8_t)NRF_RNG->VALUE;
394
395 return rnum;
396 }
397
398 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY))
399 /**
400 * Clear the resolving list
401 *
402 * @return int
403 */
404 void
ble_hw_resolv_list_clear(void)405 ble_hw_resolv_list_clear(void)
406 {
407 g_nrf_num_irks = 0;
408 }
409
410 /**
411 * Add a device to the hw resolving list
412 *
413 * @param irk Pointer to IRK to add
414 *
415 * @return int 0: success, BLE error code otherwise
416 */
417 int
ble_hw_resolv_list_add(uint8_t * irk)418 ble_hw_resolv_list_add(uint8_t *irk)
419 {
420 uint32_t *nrf_entry;
421
422 /* Find first ununsed device address match element */
423 if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
424 return BLE_ERR_MEM_CAPACITY;
425 }
426
427 /* Copy into irk list */
428 nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
429 memcpy(nrf_entry, irk, 16);
430
431 /* Add to total */
432 ++g_nrf_num_irks;
433 return BLE_ERR_SUCCESS;
434 }
435
436 /**
437 * Remove a device from the hw resolving list
438 *
439 * @param index Index of IRK to remove
440 */
441 void
ble_hw_resolv_list_rmv(int index)442 ble_hw_resolv_list_rmv(int index)
443 {
444 uint32_t *irk_entry;
445
446 if (index < g_nrf_num_irks) {
447 --g_nrf_num_irks;
448 irk_entry = &g_nrf_irk_list[index];
449 if (g_nrf_num_irks > index) {
450 memmove(irk_entry, irk_entry + 4, g_nrf_num_irks - index);
451 }
452 }
453 }
454
455 /**
456 * Returns the size of the resolving list. NOTE: this returns the maximum
457 * allowable entries in the HW. Configuration options may limit this.
458 *
459 * @return int Number of devices allowed in resolving list
460 */
461 uint8_t
ble_hw_resolv_list_size(void)462 ble_hw_resolv_list_size(void)
463 {
464 return BLE_HW_RESOLV_LIST_SIZE;
465 }
466
467 /**
468 * Called to determine if the address received was resolved.
469 *
470 * @return int Negative values indicate unresolved address; positive values
471 * indicate index in resolving list of resolved address.
472 */
473 int
ble_hw_resolv_list_match(void)474 ble_hw_resolv_list_match(void)
475 {
476 uint32_t index;
477
478 if (NRF_AAR->EVENTS_END) {
479 if (NRF_AAR->EVENTS_RESOLVED) {
480 index = NRF_AAR->STATUS;
481 return (int)index;
482 }
483 }
484
485 return -1;
486 }
487 #endif
488