/*
 * 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 <string.h>
#include "nimble/hci_common.h"
#include "host/ble_hs_hci.h"
#include "ble_hs_priv.h"

#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif

#ifndef max
#define max(a, b) ((a) > (b) ? (a) : (b))
#endif

uint16_t
ble_hs_hci_util_handle_pb_bc_join(uint16_t handle, uint8_t pb, uint8_t bc)
{
    BLE_HS_DBG_ASSERT(handle <= 0x0fff);
    BLE_HS_DBG_ASSERT(pb <= 0x03);
    BLE_HS_DBG_ASSERT(bc <= 0x03);

    return (handle  << 0)   |
           (pb      << 12)  |
           (bc      << 14);
}

int
ble_hs_hci_util_read_adv_tx_pwr(int8_t *out_tx_pwr)
{
    struct ble_hci_le_rd_adv_chan_txpwr_rp rsp;
    int rc;

    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
                                      BLE_HCI_OCF_LE_RD_ADV_CHAN_TXPWR),
                           NULL, 0, &rsp, sizeof(rsp));
    if (rc != 0) {
        return rc;
    }

    *out_tx_pwr = rsp.power_level;

    if (*out_tx_pwr < BLE_HCI_ADV_CHAN_TXPWR_MIN ||
        *out_tx_pwr > BLE_HCI_ADV_CHAN_TXPWR_MAX) {
        BLE_HS_LOG(WARN, "advertiser txpwr out of range\n");
    }

    return 0;
}

int
ble_hs_hci_rand(void *dst, int len)
{
    struct ble_hci_le_rand_rp rsp;
    uint8_t *u8ptr;
    int chunk_sz;
    int rc;

    u8ptr = dst;
    while (len > 0) {
        rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE, BLE_HCI_OCF_LE_RAND),
                               NULL, 0, &rsp, sizeof(rsp));
        if (rc != 0) {
            return rc;
        }

        chunk_sz = min(len, (int)sizeof(rsp));
        memcpy(u8ptr, &rsp.random_number, chunk_sz);

        len -= chunk_sz;
        u8ptr += chunk_sz;
    }

    return 0;
}

int
ble_hs_hci_util_read_rssi(uint16_t conn_handle, int8_t *out_rssi)
{
    struct ble_hci_rd_rssi_cp cmd;
    struct ble_hci_rd_rssi_rp rsp;

    int rc;

    cmd.handle = htole16(conn_handle);

    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_STATUS_PARAMS,
                                      BLE_HCI_OCF_RD_RSSI), &cmd, sizeof(cmd),
                           &rsp, sizeof(rsp));
    if (rc != 0) {
        return rc;
    }

    if (le16toh(rsp.handle) != conn_handle) {
        return BLE_HS_ECONTROLLER;
    }

    *out_rssi = rsp.rssi;

    return 0;
}

int
ble_hs_hci_util_set_random_addr(const uint8_t *addr)
{
    struct ble_hci_le_set_rand_addr_cp cmd;

    memcpy(cmd.addr, addr, BLE_DEV_ADDR_LEN);

    return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
                                        BLE_HCI_OCF_LE_SET_RAND_ADDR),
                             &cmd, sizeof(cmd), NULL, 0);
}

int
ble_hs_hci_util_set_data_len(uint16_t conn_handle, uint16_t tx_octets,
                             uint16_t tx_time)
{
    struct ble_hci_le_set_data_len_cp cmd;
    struct ble_hci_le_set_data_len_rp rsp;
    int rc;

    if (tx_octets < BLE_HCI_SET_DATALEN_TX_OCTETS_MIN ||
        tx_octets > BLE_HCI_SET_DATALEN_TX_OCTETS_MAX) {
        return BLE_HS_EINVAL;
    }

    if (tx_time < BLE_HCI_SET_DATALEN_TX_TIME_MIN ||
        tx_time > BLE_HCI_SET_DATALEN_TX_TIME_MAX) {
        return BLE_HS_EINVAL;
    }

    cmd.conn_handle = htole16(conn_handle);
    cmd.tx_octets = htole16(tx_octets);
    cmd.tx_time = htole16(tx_time);

    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
                                      BLE_HCI_OCF_LE_SET_DATA_LEN),
                           &cmd, sizeof(cmd), &rsp, sizeof(rsp));
    if (rc != 0) {
        return rc;
    }

    if (le16toh(rsp.conn_handle) != conn_handle) {
        return BLE_HS_ECONTROLLER;
    }

    return 0;
}

int
ble_hs_hci_util_read_sugg_def_data_len(uint16_t *out_sugg_max_tx_octets,
                                       uint16_t *out_sugg_max_tx_time)
{
    struct ble_hci_le_rd_sugg_def_data_len_rp rsp;
    int rc;

    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
                                      BLE_HCI_OCF_LE_RD_SUGG_DEF_DATA_LEN),
                           NULL, 0, &rsp, sizeof(rsp));
    if (rc != 0) {
        return rc;
    }

    *out_sugg_max_tx_octets = le16toh(rsp.max_tx_octets);
    *out_sugg_max_tx_time = le16toh(rsp.max_tx_time);

    if (*out_sugg_max_tx_octets < BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MIN ||
        *out_sugg_max_tx_octets > BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX) {
        BLE_HS_LOG(WARN,
                   "received suggested maximum tx octets is out of range\n");
    }

    if (*out_sugg_max_tx_time < BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MIN ||
        *out_sugg_max_tx_time > BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX) {
        BLE_HS_LOG(WARN,
                   "received suggested maximum tx time is out of range\n");
    }

    return 0;
}

int
ble_hs_hci_util_write_sugg_def_data_len(uint16_t sugg_max_tx_octets,
                                        uint16_t sugg_max_tx_time)
{
    struct ble_hci_le_wr_sugg_def_data_len_cp cmd;

    if (sugg_max_tx_octets < BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MIN ||
        sugg_max_tx_octets > BLE_HCI_SUGG_DEF_DATALEN_TX_OCTETS_MAX) {
        return BLE_HS_EINVAL;
    }

    if (sugg_max_tx_time < BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MIN ||
        sugg_max_tx_time > BLE_HCI_SUGG_DEF_DATALEN_TX_TIME_MAX) {
        return BLE_HS_EINVAL;
    }

    cmd.max_tx_octets = htole16(sugg_max_tx_octets);
    cmd.max_tx_time = htole16(sugg_max_tx_time);

    return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
                                        BLE_HCI_OCF_LE_WR_SUGG_DEF_DATA_LEN),
                             &cmd, sizeof(cmd), NULL, 0);
}

int
ble_hs_hci_util_data_hdr_strip(struct os_mbuf *om,
                               struct hci_data_hdr *out_hdr)
{
    int rc;

    rc = os_mbuf_copydata(om, 0, BLE_HCI_DATA_HDR_SZ, out_hdr);
    if (rc != 0) {
        return BLE_HS_ECONTROLLER;
    }

    /* Strip HCI ACL data header from the front of the packet. */
    os_mbuf_adj(om, BLE_HCI_DATA_HDR_SZ);

    out_hdr->hdh_handle_pb_bc = get_le16(&out_hdr->hdh_handle_pb_bc);
    out_hdr->hdh_len = get_le16(&out_hdr->hdh_len);

    return 0;
}

int
ble_hs_hci_read_chan_map(uint16_t conn_handle, uint8_t *out_chan_map)
{
    struct ble_hci_le_rd_chan_map_cp cmd;
    struct ble_hci_le_rd_chan_map_rp rsp;
    int rc;

    cmd.conn_handle = htole16(conn_handle);

    rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
                                      BLE_HCI_OCF_LE_RD_CHAN_MAP),
                           &cmd, sizeof(cmd), &rsp, sizeof(rsp));
    if (rc != 0) {
        return rc;
    }

    if (le16toh(rsp.conn_handle) != conn_handle) {
        return BLE_HS_ECONTROLLER;
    }

    memcpy(out_chan_map, rsp.chan_map, 5);

    return 0;
}

int
ble_hs_hci_set_chan_class(const uint8_t *chan_map)
{
    struct ble_hci_le_set_host_chan_class_cp cmd;

    memcpy(cmd.chan_map, chan_map, sizeof(cmd.chan_map));

    return ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
                                        BLE_HCI_OCF_LE_SET_HOST_CHAN_CLASS),
                             &cmd, sizeof(cmd), NULL, 0);
}
