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