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