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