/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include <stdint.h>
#include <assert.h>
#include <string.h>
#include "syscfg/syscfg.h"
#include "os/os.h"
#include "nimble/ble.h"
#include "nimble/nimble_opt.h"
#include "controller/ble_hw.h"
#include "controller/ble_ll.h"
#if MYNEWT_VAL(TRNG)
#include "trng/trng.h"
#endif

#if MYNEWT_VAL(TRNG)
static struct trng_dev *g_trng;
#else
/* This is a simple circular buffer for holding N samples of random data */
struct ble_ll_rnum_data
{
    uint8_t *rnd_in;
    uint8_t *rnd_out;
    volatile uint8_t rnd_size;
};

struct ble_ll_rnum_data g_ble_ll_rnum_data;
uint8_t g_ble_ll_rnum_buf[MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)];

#define IS_RNUM_BUF_END(x)  \
    (x == &g_ble_ll_rnum_buf[MYNEWT_VAL(BLE_LL_RNG_BUFSIZE) - 1])

void
ble_ll_rand_sample(uint8_t rnum)
{
    os_sr_t sr;

    OS_ENTER_CRITICAL(sr);
    if (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)) {
        ++g_ble_ll_rnum_data.rnd_size;
        g_ble_ll_rnum_data.rnd_in[0] = rnum;
        if (IS_RNUM_BUF_END(g_ble_ll_rnum_data.rnd_in)) {
            g_ble_ll_rnum_data.rnd_in = g_ble_ll_rnum_buf;
        } else {
            ++g_ble_ll_rnum_data.rnd_in;
        }
    } else {
        /* Stop generating random numbers as we are full */
        ble_hw_rng_stop();
    }
    OS_EXIT_CRITICAL(sr);
}
#endif

/* Get 'len' bytes of random data */
int
ble_ll_rand_data_get(uint8_t *buf, uint8_t len)
{
#if MYNEWT_VAL(TRNG)
    size_t num;

    while (len) {
        num = trng_read(g_trng, buf, len);
        buf += num;
        len -= num;
    }
#else
    uint8_t rnums;
    os_sr_t sr;

    while (len != 0) {
        OS_ENTER_CRITICAL(sr);
        rnums = g_ble_ll_rnum_data.rnd_size;
        if (rnums > len) {
            rnums = len;
        }
        len -= rnums;
        g_ble_ll_rnum_data.rnd_size -= rnums;
        while (rnums) {
            buf[0] = g_ble_ll_rnum_data.rnd_out[0];
            if (IS_RNUM_BUF_END(g_ble_ll_rnum_data.rnd_out)) {
                g_ble_ll_rnum_data.rnd_out = g_ble_ll_rnum_buf;
            } else {
                ++g_ble_ll_rnum_data.rnd_out;
            }
            ++buf;
            --rnums;
        }
        OS_EXIT_CRITICAL(sr);

        /* Make sure rng is started! */
        ble_hw_rng_start();

        /* Wait till bytes are in buffer. */
        if (len) {
            while ((g_ble_ll_rnum_data.rnd_size < len) &&
                   (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE))) {
                /* Spin here */
            }
        }
    }
#endif
    return BLE_ERR_SUCCESS;
}

/**
 * Called to obtain a "prand" as defined in core V4.2 Vol 6 Part B 1.3.2.2
 *
 * @param prand
 */
void
ble_ll_rand_prand_get(uint8_t *prand)
{
    uint16_t sum;

    while (1) {
        /* Get 24 bits of random data */
        ble_ll_rand_data_get(prand, 3);

        /* Prand cannot be all zeros or 1's. */
        sum = prand[0] + prand[1] + prand[2];
        if ((sum != 0) && (sum != (3 * 0xff))) {
            break;
        }
    }

    /* Upper two bits must be 01 */
    prand[2] &= ~0xc0;
    prand[2] |= 0x40;
}

/**
 * Start the generation of random numbers
 *
 * @return int
 */
int
ble_ll_rand_start(void)
{
#if MYNEWT_VAL(TRNG)
    /* Nothing to do - this is handled by driver */
#else
    /* Start the generation of numbers if we are not full */
    if (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)) {
        ble_hw_rng_start();
    }
#endif
    return 0;
}

/**
 * Initialize LL random number generation. Should be called only once on
 * initialization.
 *
 * @return int
 */
int
ble_ll_rand_init(void)
{
#if MYNEWT_VAL(TRNG)
    g_trng = (struct trng_dev *) os_dev_open("trng", OS_TIMEOUT_NEVER, NULL);
#else
    g_ble_ll_rnum_data.rnd_in = g_ble_ll_rnum_buf;
    g_ble_ll_rnum_data.rnd_out = g_ble_ll_rnum_buf;
    ble_hw_rng_init(ble_ll_rand_sample, 1);
#endif
    return 0;
}
