blob: d4cd6fbde61f61e2c0e9b31ef516a168aa66a60a [file] [log] [blame]
/*
* Copyright (c) 2019 Intel corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <init.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <kernel.h>
#include <mipi_syst.h>
#include <logging/log.h>
#include <logging/log_ctrl.h>
#include <logging/log_output.h>
static struct mipi_syst_header log_syst_header;
static struct mipi_syst_handle log_syst_handle;
#if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_STATE_DATA)
static const char pattern[] = "SYS-T RAW DATA: ";
static const char valToHex[] = "0123456789ABCDEF";
static int out_func(int c, void *ctx)
{
const struct log_output *out_ctx = (const struct log_output *)ctx;
out_ctx->buf[out_ctx->control_block->offset] = (u8_t)c;
out_ctx->control_block->offset++;
__ASSERT_NO_MSG(out_ctx->control_block->offset <= out_ctx->size);
if (out_ctx->control_block->offset == out_ctx->size) {
log_output_flush(out_ctx);
}
return 0;
}
static void write_raw(struct mipi_syst_handle *systh, const void *p, int n)
{
int i;
u8_t c;
#if defined(MIPI_SYST_BIG_ENDIAN)
for (i = n - 1; i >= 0; --i) {
#else
for (i = 0; i < n; ++i) {
#endif
c = ((const u8_t *)p)[i];
out_func(valToHex[c >> 0x4], systh->systh_platform.log_output);
out_func(valToHex[c & 0xF], systh->systh_platform.log_output);
}
}
static void write_d8(struct mipi_syst_handle *systh, u8_t v)
{
write_raw(systh, &v, sizeof(v));
}
static void write_d16(struct mipi_syst_handle *systh, u16_t v)
{
write_raw(systh, &v, sizeof(v));
}
static void write_d32(struct mipi_syst_handle *systh, u32_t v)
{
write_raw(systh, &v, sizeof(v));
}
#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO)
static void write_d64(struct mipi_syst_handle *systh, u64_t v)
{
write_raw(systh, &v, sizeof(v));
}
#endif
static void write_d32ts(struct mipi_syst_handle *systh, u32_t v)
{
for (int i = 0; i < strlen(pattern); i++) {
out_func(pattern[i], systh->systh_platform.log_output);
}
write_raw(systh, &v, sizeof(v));
}
static void write_flag(struct mipi_syst_handle *systh)
{
u32_t flag = systh->systh_platform.flag;
if ((flag & LOG_OUTPUT_FLAG_CRLF_NONE) != 0U) {
return;
}
if ((flag & LOG_OUTPUT_FLAG_CRLF_LFONLY) != 0U) {
out_func('\n', systh->systh_platform.log_output);
} else {
out_func('\r', systh->systh_platform.log_output);
out_func('\n', systh->systh_platform.log_output);
}
}
#endif
#if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP)
mipi_syst_u64 mipi_syst_get_epoch(void)
{
return k_uptime_ticks();
}
#endif
static void update_systh_platform_data(struct mipi_syst_handle *handle,
const struct log_output *log_output,
u32_t flag)
{
#if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_STATE_DATA)
handle->systh_platform.flag = (mipi_syst_u32)flag;
handle->systh_platform.log_output = (struct log_output *)log_output;
#endif
}
#if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
/*
* Platform specific SyS-T handle initialization hook function
*
* @param systh pointer to the SyS-T handle structure
*/
static void platform_handle_init(struct mipi_syst_handle *systh)
{
#if defined(MIPI_SYST_PCFG_LENGTH_FIELD)
MIPI_SYST_ENABLE_HANDLE_LENGTH(systh, 1);
#endif
#if defined(MIPI_SYST_PCFG_ENABLE_TIMESTAMP)
MIPI_SYST_ENABLE_HANDLE_TIMESTAMP(systh, 1);
#endif
}
static void platform_handle_release(struct mipi_syst_handle *systh)
{
ARG_UNUSED(systh);
}
#endif
/*
* Platform specific global state initialization hook function
*
* @param systh pointer to the new SyS-T handle structure
* @param platform_data user defined data for the init function.
*
*/
static void mipi_syst_platform_init(struct mipi_syst_header *systh,
const void *platform_data)
{
#if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_HANDLE_DATA)
systh->systh_inith = platform_handle_init;
systh->systh_releaseh = platform_handle_release;
#endif
#if defined(MIPI_SYST_PCFG_ENABLE_PLATFORM_STATE_DATA)
systh->systh_platform.write_d8 = write_d8;
systh->systh_platform.write_d16 = write_d16;
systh->systh_platform.write_d32 = write_d32;
#if defined(MIPI_SYST_PCFG_ENABLE_64BIT_IO)
systh->systh_platform.write_d64 = write_d64;
#endif
systh->systh_platform.write_d32ts = write_d32ts;
systh->systh_platform.write_flag = write_flag;
#endif
}
/*
* 0 MIPI_SYST_SEVERITY_MAX no assigned severity
* 1 MIPI_SYST_SEVERITY_FATAL critical error level
* 2 MIPI_SYST_SEVERITY_ERROR error message level
* 3 MIPI_SYST_SEVERITY_WARNING warning message level
* 4 MIPI_SYST_SEVERITY_INFO information message level
* 5 MIPI_SYST_SEVERITY_USER1 user defined level 5
* 6 MIPI_SYST_SEVERITY_USER2 user defined level 6
* 7 MIPI_SYST_SEVERITY_DEBUG debug information level
*/
static u32_t level_to_syst_severity(u32_t level)
{
u32_t ret;
switch (level) {
case LOG_LEVEL_NONE:
ret = 0U;
break;
case LOG_LEVEL_ERR:
ret = 2U;
break;
case LOG_LEVEL_WRN:
ret = 3U;
break;
case LOG_LEVEL_INF:
ret = 4U;
break;
case LOG_LEVEL_DBG:
ret = 7U;
break;
default:
ret = 7U;
break;
}
return ret;
}
static void std_print(struct log_msg *msg,
const struct log_output *log_output)
{
const char *str = log_msg_str_get(msg);
u32_t nargs = log_msg_nargs_get(msg);
u32_t *args = alloca(sizeof(u32_t)*nargs);
u32_t severity = level_to_syst_severity(log_msg_level_get(msg));
for (int i = 0; i < nargs; i++) {
args[i] = log_msg_arg_get(msg, i);
}
switch (log_msg_nargs_get(msg)) {
case 0:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str);
break;
case 1:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0]);
break;
case 2:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1]);
break;
case 3:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2]);
break;
case 4:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3]);
break;
case 5:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4]);
break;
case 6:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4], args[5]);
break;
case 7:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4], args[5],
args[6]);
break;
case 8:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4], args[5],
args[6], args[7]);
break;
case 9:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4], args[5],
args[6], args[7], args[8]);
break;
case 10:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4], args[5],
args[6], args[7], args[8], args[9]);
break;
case 11:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4], args[5],
args[6], args[7], args[8], args[9], args[10]);
break;
case 12:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4], args[5],
args[6], args[7], args[8], args[9], args[10],
args[11]);
break;
case 13:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4], args[5],
args[6], args[7], args[8], args[9], args[10],
args[11], args[12]);
break;
case 14:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4], args[5],
args[6], args[7], args[8], args[9], args[10],
args[11], args[12], args[13]);
break;
case 15:
MIPI_SYST_PRINTF(&log_syst_handle, severity, str, args[0],
args[1], args[2], args[3], args[4], args[5],
args[6], args[7], args[8], args[9], args[10],
args[11], args[12], args[13], args[14]);
break;
default:
/* Unsupported number of arguments. */
__ASSERT_NO_MSG(true);
break;
}
}
static void raw_string_print(struct log_msg *msg,
const struct log_output *log_output)
{
char buf[CONFIG_LOG_STRDUP_MAX_STRING + 1];
size_t length = CONFIG_LOG_STRDUP_MAX_STRING;
u32_t severity = level_to_syst_severity(log_msg_level_get(msg));
log_msg_hexdump_data_get(msg, buf, &length, 0);
buf[length] = '\0';
MIPI_SYST_PRINTF(&log_syst_handle, severity, buf);
}
static void hexdump_print(struct log_msg *msg,
const struct log_output *log_output)
{
char buf[CONFIG_LOG_STRDUP_MAX_STRING + 1];
size_t length = CONFIG_LOG_STRDUP_MAX_STRING;
u32_t severity = level_to_syst_severity(log_msg_level_get(msg));
log_msg_hexdump_data_get(msg, buf, &length, 0);
MIPI_SYST_WRITE(&log_syst_handle, severity, 0x1A, buf, length);
}
void log_output_msg_syst_process(const struct log_output *log_output,
struct log_msg *msg, u32_t flag)
{
u8_t level = (u8_t)log_msg_level_get(msg);
bool raw_string = (level == LOG_LEVEL_INTERNAL_RAW_STRING);
update_systh_platform_data(&log_syst_handle, log_output, flag);
if (log_msg_is_std(msg)) {
std_print(msg, log_output);
} else if (raw_string) {
raw_string_print(msg, log_output);
} else {
hexdump_print(msg, log_output);
}
}
void log_output_string_syst_process(const struct log_output *log_output,
struct log_msg_ids src_level,
const char *fmt, va_list ap, u32_t flag)
{
u8_t str[CONFIG_LOG_STRDUP_MAX_STRING];
size_t length = CONFIG_LOG_STRDUP_MAX_STRING;
u32_t severity = level_to_syst_severity((u32_t)src_level.level);
length = vsnprintk(str, length, fmt, ap);
str[length] = '\0';
update_systh_platform_data(&log_syst_handle, log_output, flag);
MIPI_SYST_PRINTF(&log_syst_handle, severity, str);
}
void log_output_hexdump_syst_process(const struct log_output *log_output,
struct log_msg_ids src_level,
const u8_t *data, u32_t length, u32_t flag)
{
u32_t severity = level_to_syst_severity((u32_t)src_level.level);
update_systh_platform_data(&log_syst_handle, log_output, flag);
MIPI_SYST_WRITE(&log_syst_handle, severity, 0x1A, data, length);
}
static int syst_init(struct device *arg)
{
ARG_UNUSED(arg);
MIPI_SYST_INIT_STATE(&log_syst_header,
mipi_syst_platform_init, (void *)0);
MIPI_SYST_INIT_HANDLE_STATE(&log_syst_header,
&log_syst_handle, NULL);
return 0;
}
SYS_INIT(syst_init, POST_KERNEL, 0);