/*
 * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or
 * an affiliate of Cypress Semiconductor Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @brief PSoC 6 BLE (BLESS) driver.
 */

#include <errno.h>
#include <stddef.h>
#include <string.h>

#include <zephyr/arch/cpu.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/drivers/bluetooth/hci_driver.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/init.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/util.h>
#include "zephyr/logging/log.h"

#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
#define LOG_LEVEL      CONFIG_BT_HCI_DRIVER_LOG_LEVEL
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(psoc6_bless);

#include "cy_ble_stack_pvt.h"
#include "cycfg_ble.h"

#define DT_DRV_COMPAT infineon_cat1_bless_hci

#define PACKET_TYPE_HCI_COMMAND     0X1
#define PACKET_TYPE_HCI_ACL_DATA    0x2
#define PACKET_TYPE_HCI_SYNCHRONOUS 0X3
#define PACKET_TYPE_HCI_EVENT       0X4

#define BLE_LOCK_TMOUT_MS       (1000)
#define BLE_THREAD_SEM_TMOUT_MS (1000)

#define CYBLE_STACK_SIZE (CY_BLE_STACK_RAM_SIZE + 4096)

#define PSOC6_BLESS_OP_SET_PUBLIC_ADDR BT_OP(BT_OGF_VS, 0x1a0)

static K_SEM_DEFINE(psoc6_bless_rx_sem, 0, 1);
static K_SEM_DEFINE(psoc6_bless_operation_sem, 1, 1);
static K_KERNEL_STACK_DEFINE(psoc6_bless_rx_thread_stack, CONFIG_BT_RX_STACK_SIZE);
static struct k_thread psoc6_bless_rx_thread_data;
static cy_stc_ble_hci_tx_packet_info_t hci_tx_pkt;

extern void Cy_BLE_EnableLowPowerMode(void);

CY_ALIGN(sizeof(uint32_t)) CY_NOINIT uint8_t psoc6_bless_stack_memory[CYBLE_STACK_SIZE];

/** BLE Stack parameters */
static cy_stc_ble_stack_params_t psoc6_bless_stack_param = {
	.memoryHeapPtr = psoc6_bless_stack_memory,
	.totalHeapSz = CYBLE_STACK_SIZE,
	.dleMaxTxCapability = CONFIG_BT_PSOC6_BLESS_MAX_TX_PAYLOAD,
	.dleMaxRxCapability = CONFIG_BT_PSOC6_BLESS_MAX_RX_PAYLOAD,
	.featureMask = (CY_BLE_DLE_FEATURE | CY_BLE_LL_PRIVACY_FEATURE |
			CY_BLE_SECURE_CONN_FEATURE | CY_BLE_PHY_UPDATE_FEATURE |
			CY_BLE_STORE_BONDLIST_FEATURE | CY_BLE_STORE_RESOLVING_LIST_FEATURE |
			CY_BLE_STORE_WHITELIST_FEATURE | CY_BLE_TX_POWER_CALIBRATION_FEATURE),
	.maxConnCount = CY_BLE_CONN_COUNT,
	.tx5dbmModeEn = CY_BLE_ENABLE_TX_5DBM,
};

static const cy_stc_sysint_t psoc6_bless_isr_cfg = {
	.intrSrc = DT_INST_IRQN(0),
	.intrPriority = DT_INST_IRQ(0, priority),
};

static cy_stc_ble_hw_config_t psoc6_bless_hw_config = {
	.blessIsrConfig = &psoc6_bless_isr_cfg,
};

static const cy_stc_ble_config_t psoc6_bless_config = {
	.stackParam = &psoc6_bless_stack_param,
	.hw = &psoc6_bless_hw_config,
};

static void psoc6_bless_rx_thread(void *, void *, void *)
{
	while (true) {
		k_sem_take(&psoc6_bless_rx_sem, K_MSEC(BLE_THREAD_SEM_TMOUT_MS));
		Cy_BLE_ProcessEvents();
	}
}

static void psoc6_bless_isr_handler(const struct device *dev)
{
	if (Cy_BLE_HAL_BlessInterruptHandler()) {
		k_sem_give(&psoc6_bless_rx_sem);
	}
}

static void psoc6_bless_events_handler(uint32_t eventCode, void *eventParam)
{
	cy_stc_ble_hci_tx_packet_info_t *hci_rx = NULL;
	struct net_buf *buf = NULL;
	size_t buf_tailroom = 0;

	if (eventCode != CY_BLE_EVT_HCI_PKT_RCVD) {
		LOG_DBG("Other EVENT 0x%X", eventCode);
		return;
	}

	hci_rx = eventParam;

	switch (hci_rx->packetType) {
	case PACKET_TYPE_HCI_EVENT:
		buf = bt_buf_get_evt(hci_rx->data[0], 0, K_NO_WAIT);
		if (!buf) {
			LOG_ERR("Failed to allocate the buffer for RX: EVENT ");
			return;
		}

		break;
	case PACKET_TYPE_HCI_ACL_DATA:
		buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT);
		if (!buf) {
			LOG_ERR("Failed to allocate the buffer for RX: ACL ");
			return;
		}
		bt_buf_set_type(buf, BT_BUF_ACL_IN);

		break;

	default:
		LOG_WRN("Unsupported HCI Packet Received");
		return;
	}

	buf_tailroom = net_buf_tailroom(buf);
	if (buf_tailroom < hci_rx->dataLength) {
		LOG_WRN("Not enough space for rx data");
		return;
	}
	net_buf_add_mem(buf, hci_rx->data, hci_rx->dataLength);
	bt_recv(buf);
}

static int psoc6_bless_open(void)
{
	k_tid_t tid;

	tid = k_thread_create(&psoc6_bless_rx_thread_data, psoc6_bless_rx_thread_stack,
			      K_KERNEL_STACK_SIZEOF(psoc6_bless_rx_thread_stack),
			      psoc6_bless_rx_thread, NULL, NULL, NULL,
			      K_PRIO_COOP(CONFIG_BT_RX_PRIO), 0, K_NO_WAIT);
	k_thread_name_set(tid, "psoc6_bless_rx_thread");

	return 0;
}

static int psoc6_bless_send(struct net_buf *buf)
{
	cy_en_ble_api_result_t result;

	memset(&hci_tx_pkt, 0, sizeof(cy_stc_ble_hci_tx_packet_info_t));

	hci_tx_pkt.dataLength = buf->len;
	hci_tx_pkt.data = buf->data;

	switch (bt_buf_get_type(buf)) {
	case BT_BUF_ACL_OUT:
		hci_tx_pkt.packetType = PACKET_TYPE_HCI_ACL_DATA;
		break;
	case BT_BUF_CMD:
		hci_tx_pkt.packetType = PACKET_TYPE_HCI_COMMAND;
		break;
	default:
		net_buf_unref(buf);
		return -ENOTSUP;
	}

	if (k_sem_take(&psoc6_bless_operation_sem, K_MSEC(BLE_LOCK_TMOUT_MS)) != 0) {
		LOG_ERR("Failed to acquire BLE DRV Semaphore");
		net_buf_unref(buf);
		return -EIO;
	}

	result = Cy_BLE_SoftHciSendAppPkt(&hci_tx_pkt);
	if (result != CY_BLE_SUCCESS) {
		LOG_ERR("Error in sending packet reason %d\r\n", result);
	}

	k_sem_give(&psoc6_bless_operation_sem);

	net_buf_unref(buf);

	return 0;
}

static int psoc6_bless_setup(void)
{
	struct net_buf *buf;
	int err;
	uint8_t *addr = (uint8_t *)&SFLASH_BLE_DEVICE_ADDRESS[0];
	uint8_t hci_data[] = {
		addr[5], addr[4], addr[3], addr[2], addr[1], addr[0], BT_ADDR_LE_PUBLIC,
	};

	buf = bt_hci_cmd_create(PSOC6_BLESS_OP_SET_PUBLIC_ADDR, sizeof(hci_data));
	if (buf == NULL) {
		LOG_ERR("Unable to allocate command buffer");
		return -ENOMEM;
	}

	/* Add data part of packet */
	net_buf_add_mem(buf, hci_data, sizeof(hci_data));

	err = bt_hci_cmd_send_sync(PSOC6_BLESS_OP_SET_PUBLIC_ADDR, buf, NULL);
	if (err) {
		return err;
	}

	return 0;
}

static int psoc6_bless_hci_init(void)
{
	cy_en_ble_api_result_t result;
	static const struct bt_hci_driver drv = {
		.name = "PSoC 6 BLESS",
		.bus = BT_HCI_DRIVER_BUS_VIRTUAL,
		.quirks = BT_QUIRK_NO_RESET,
		.open = psoc6_bless_open,
		.send = psoc6_bless_send,
		.setup = psoc6_bless_setup,
	};

	/* Connect BLE interrupt to ISR */
	IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), psoc6_bless_isr_handler, 0, 0);

	/* Registers the generic callback functions.  */
	Cy_BLE_RegisterEventCallback(psoc6_bless_events_handler);

	/* Initializes the PSoC 6 BLESS Controller. */
	result = Cy_BLE_InitController(&psoc6_bless_config);
	if (result != CY_BLE_SUCCESS) {
		LOG_ERR("Failed to init the BLE Controller");
		return -EIO;
	}

	/* Enables the BLESS controller in HCI only mode. */
	result = Cy_BLE_EnableHCIModeController();
	if (result != CY_BLE_SUCCESS) {
		LOG_ERR("Failed to enable the BLE Controller in hci mode");
		return -EIO;
	}

	/* Enables BLE Low-power mode (LPM)*/
	Cy_BLE_EnableLowPowerMode();

	/* Register a BLESS HCI driver to the Bluetooth stack. */
	bt_hci_driver_register(&drv);

	return 0;
}

SYS_INIT(psoc6_bless_hci_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
