/*
<:copyright-BRCM:2016:DUAL/GPL:standard

   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
   All Rights Reserved

Unless you and Broadcom execute a separate written software license
agreement governing use of this software, this software is licensed
to you under the terms of the GNU General Public License version 2
(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
with the following added to such license:

   As a special exception, the copyright holders of this software give
   you permission to link this software with independent modules, and
   to copy and distribute the resulting executable under terms of your
   choice, provided that you also meet, for each linked independent
   module, the terms and conditions of the license of that module.
   An independent module is a module which is not derived from this
   software.  The special exception does not apply to any modifications
   of the software.

Not withstanding the above, under no circumstances may you combine
this software in any way with any other Broadcom software provided
under a license other than the GPL, without Broadcom's express prior
written consent.

:>
 */

/*
 * bcm_dev_log_linux.c
 *
 * Linux-specific code. User space
 */

#include <bcmolt_dev_log_linux.h>
#include <kernel/bcmolt_dev_log_ioctl.h>

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <fcntl.h>

#define BCM_DEV_LOG_FILE_NAME           "/dev/bcm_log"
#define BCM_DEV_LOG_POLL_INTERVAL_US    10000

static int dev_log_file;
static bcmos_task dev_log_read_task;
static int max_kernel_id_index;
/*
 * Internal helpers
 */

/* read kernel DB */
static bcmos_errno _dev_log_kernel_db_read(void)
{
    dev_log_io_param io_param;
    int i;

    if (ioctl(dev_log_file, DEV_LOG_CHRDEV_DB_READ, &io_param) == -1)
    {
        BCMOS_TRACE_RETURN(BCM_ERR_IO, "Can't read kernel data base. Error %s\n", strerror(errno));
    }

    /* Register kernel log ids */
    for (i=0; i<io_param.db_read.num_ids; i++)
    {
        bcm_dev_log_id_register(io_param.db_read.ids[i].name,
            io_param.db_read.ids[i].default_level,
            io_param.db_read.ids[i].default_type);
    }
    max_kernel_id_index = i;

    return BCM_ERR_OK;
}

/* identify log level by level char */
static bcm_dev_log_level _dev_log_level_by_char(char clevel)
{
    bcm_dev_log_level level;

    switch (clevel)
    {
    case 'F': level = DEV_LOG_LEVEL_FATAL; break;
    case 'E': level = DEV_LOG_LEVEL_ERROR; break;
    case 'W': level = DEV_LOG_LEVEL_WARNING; break;
    case 'I': level = DEV_LOG_LEVEL_INFO; break;
    case 'D': level = DEV_LOG_LEVEL_DEBUG; break;
    default: level = DEV_LOG_LEVEL_NO_LOG; break;
    }

    return level;
}

/* read_buf task handler */
static int _dev_log_read_kernel_buf_handler(long data)
{
    dev_log_io_param io_param = {};
    unsigned long log_time;
    char level_char;
    char log_name[MAX_DEV_LOG_ID_NAME];
    int n;
    dev_log_id id;
    bcm_dev_log_level level;

    while (dev_log_file)
    {
        if (ioctl(dev_log_file, DEV_LOG_CHRDEV_MSG_READ, &io_param) < 0)
        {
            /* If no entries - sleep ant retry. Otherwise - stop */
            if (errno == EAGAIN)
            {
                bcmos_usleep(BCM_DEV_LOG_POLL_INTERVAL_US);
                continue;
            }
            BCMOS_TRACE_ERR("ioctl()->%d (%s)\n", errno, strerror(errno));
            break;
        }

        /* parse kernel message */
        n = sscanf(io_param.msg_read.msg, "[%lu: %c %20s]", &log_time, &level_char, log_name);
        if (n < 3)
        {
            BCMOS_TRACE_ERR("Can't parse kernel log: %s\n", io_param.msg_read.msg);
            continue;
        }

        /* Identify log_id */
        id = bcm_dev_log_id_get_by_name(log_name);
        if (id == DEV_LOG_INVALID_ID)
        {
            BCMOS_TRACE_ERR("Can't identify log id: %s\n", io_param.msg_read.msg);
            continue;
        }

        /* Identify log_level */
        level = _dev_log_level_by_char(level_char);
        if (level == DEV_LOG_LEVEL_NO_LOG)
        {
            BCMOS_TRACE_ERR("Can't identify log level: %s\n", io_param.msg_read.msg);
            continue;
        }

        /* log kernel message in user-space logger.
         * Do not generate header. It is already in the message
         */
        bcm_dev_log_log(id, level, BCM_LOG_FLAG_NO_HEADER | BCM_LOG_FLAG_CALLER_FMT, "%s", io_param.msg_read.msg);
    }
    BCMOS_TRACE_INFO("Kernel logger daemon terminated\n");

    return 0;
}

/** Linux-specific init */
bcmos_errno bcm_dev_log_linux_init(void)
{
    static char *task_name = "kernel_log";
    bcmos_task_parm taskp =
    {
        .name = task_name,
        .priority = TASK_PRIORITY_DEV_LOG_KERNEL,
        .handler = _dev_log_read_kernel_buf_handler
    };
    bcmos_errno rc;

    if (dev_log_file)
        return BCM_ERR_ALREADY;

    /* Read kernel registrations */
    dev_log_file = open(BCM_DEV_LOG_FILE_NAME, O_RDWR);
    if (dev_log_file < 0)
    {
        dev_log_file = 0;
        BCMOS_TRACE_RETURN(BCM_ERR_NOENT, "Can't open %s for read/write. Error %s\n",
            BCM_DEV_LOG_FILE_NAME, strerror(errno));
    }

    /* Read kernel data base */
    rc = _dev_log_kernel_db_read();
    if (rc)
    {
        close(dev_log_file);
        dev_log_file = 0;
        return rc;
    }

    /* Create a task that will poll kernel buffer */
    rc = bcmos_task_create(&dev_log_read_task, &taskp);
    if (rc)
    {
        close(dev_log_file);
        dev_log_file = 0;
        BCMOS_TRACE_RETURN(rc, "Can't create read_kernel_buf task\n");
    }

    return BCM_ERR_OK;
}

/** Linux-specific cleanup */
void bcm_dev_log_linux_exit(void)
{
    int f = dev_log_file;
    if (!dev_log_file)
        return;
    dev_log_file = 0;
    close(f); /* will cause pending ioctl to unlock */
    bcmos_task_destroy(&dev_log_read_task);
}

/* notify dev_log in kernel space about log_type change */
bcmos_errno bcm_dev_log_linux_id_set_type(dev_log_id log_id, bcm_dev_log_id_type log_type)
{
    dev_log_io_param io_param;
    uint32_t idx;

    if (!dev_log_file)
        return BCM_ERR_STATE;

    /* map to index. id in kernel space is different */
    idx = bcm_dev_log_get_index_by_id(log_id);
    if (idx == DEV_LOG_INVALID_INDEX)
    {
        BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Can't map log_id to index\n");
    }

    /* Ignore the request if log_id is not in th ekernel */
    if (idx > max_kernel_id_index)
        return BCM_ERR_OK;

    io_param.type_set.index = idx;
    io_param.type_set.type = log_type;
    if (ioctl(dev_log_file, DEV_LOG_CHRDEV_TYPE_SET, &io_param) == -1)
    {
        BCMOS_TRACE_RETURN(BCM_ERR_IO, "Can't set type for kernel log id %lu. Error %s\n", log_id, strerror(errno));
    }

    return BCM_ERR_OK;
}

/* notify dev_log in kernel space about log_level change */
bcmos_errno bcm_dev_log_linux_id_set_level(dev_log_id log_id, bcm_dev_log_level log_level_print, bcm_dev_log_level log_level_save)
{
    uint32_t idx;
    dev_log_io_param io_param;

    if (!dev_log_file)
        return BCM_ERR_STATE;

    /* map to index. id in kernel space is different */
    idx = bcm_dev_log_get_index_by_id(log_id);
    if (idx == DEV_LOG_INVALID_INDEX)
    {
        BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Can't map log_id to index\n");
    }

    /* Ignore the request if log_id is not in the kernel */
    if (idx > max_kernel_id_index)
        return BCM_ERR_OK;

    io_param.level_set.index = idx;
    io_param.level_set.level_print = log_level_print;
    io_param.level_set.level_save = log_level_save;

    if (ioctl(dev_log_file, DEV_LOG_CHRDEV_LEVEL_SET, &io_param) == -1)
    {
        BCMOS_TRACE_RETURN(BCM_ERR_IO, "Can't set level for kernel log id %lu. Error %s\n", log_id, strerror(errno));
    }

    return BCM_ERR_OK;
}
