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