blob: c83ee24e21172bb96d41bdeaeffd690903e1c49c [file] [log] [blame]
/*
* 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 <assert.h>
#include <string.h>
#include "os/mynewt.h"
#include <hal/hal_system.h>
#include <hal/hal_watchdog.h>
#include <mgmt/mgmt.h>
#include <console/console.h>
#include <datetime/datetime.h>
#if MYNEWT_VAL(LOG_SOFT_RESET)
#include <reboot/log_reboot.h>
#endif
#include "nmgr_os/nmgr_os.h"
#include <tinycbor/cbor.h>
#include <cborattr/cborattr.h>
static struct os_callout nmgr_reset_callout;
static int nmgr_def_echo(struct mgmt_cbuf *);
static int nmgr_def_console_echo(struct mgmt_cbuf *);
static int nmgr_def_taskstat_read(struct mgmt_cbuf *njb);
static int nmgr_def_mpstat_read(struct mgmt_cbuf *njb);
static int nmgr_datetime_get(struct mgmt_cbuf *njb);
static int nmgr_datetime_set(struct mgmt_cbuf *njb);
static int nmgr_reset(struct mgmt_cbuf *njb);
static const struct mgmt_handler nmgr_def_group_handlers[] = {
[NMGR_ID_ECHO] = {
nmgr_def_echo, nmgr_def_echo
},
[NMGR_ID_CONS_ECHO_CTRL] = {
nmgr_def_console_echo, nmgr_def_console_echo
},
[NMGR_ID_TASKSTATS] = {
nmgr_def_taskstat_read, NULL
},
[NMGR_ID_MPSTATS] = {
nmgr_def_mpstat_read, NULL
},
[NMGR_ID_DATETIME_STR] = {
nmgr_datetime_get, nmgr_datetime_set
},
[NMGR_ID_RESET] = {
NULL, nmgr_reset
},
};
#define NMGR_DEF_GROUP_SZ \
(sizeof(nmgr_def_group_handlers) / sizeof(nmgr_def_group_handlers[0]))
static struct mgmt_group nmgr_def_group = {
.mg_handlers = (struct mgmt_handler *)nmgr_def_group_handlers,
.mg_handlers_count = NMGR_DEF_GROUP_SZ,
.mg_group_id = MGMT_GROUP_ID_DEFAULT
};
static int
nmgr_def_echo(struct mgmt_cbuf *cb)
{
char echo_buf[128] = {'\0'};
CborError g_err = CborNoError;
struct cbor_attr_t attrs[2] = {
[0] = {
.attribute = "d",
.type = CborAttrTextStringType,
.addr.string = echo_buf,
.nodefault = 1,
.len = sizeof(echo_buf),
},
[1] = {
.attribute = NULL
}
};
g_err |= cbor_encode_text_stringz(&cb->encoder, "r");
g_err |= cbor_read_object(&cb->it, attrs);
g_err |= cbor_encode_text_string(&cb->encoder, echo_buf, strlen(echo_buf));
if (g_err) {
return MGMT_ERR_ENOMEM;
}
return (0);
}
static int
nmgr_def_console_echo(struct mgmt_cbuf *cb)
{
long long int echo_on = 1;
int rc;
struct cbor_attr_t attrs[2] = {
[0] = {
.attribute = "echo",
.type = CborAttrIntegerType,
.addr.integer = &echo_on,
.nodefault = 1
},
[1] = { 0 },
};
rc = cbor_read_object(&cb->it, attrs);
if (rc) {
return MGMT_ERR_EINVAL;
}
if (echo_on) {
console_echo(1);
} else {
console_echo(0);
}
return (0);
}
static int
nmgr_def_taskstat_read(struct mgmt_cbuf *cb)
{
struct os_task *prev_task;
struct os_task_info oti;
CborError g_err = CborNoError;
CborEncoder tasks;
CborEncoder task;
g_err |= cbor_encode_text_stringz(&cb->encoder, "rc");
g_err |= cbor_encode_int(&cb->encoder, MGMT_ERR_EOK);
g_err |= cbor_encode_text_stringz(&cb->encoder, "tasks");
g_err |= cbor_encoder_create_map(&cb->encoder, &tasks,
CborIndefiniteLength);
prev_task = NULL;
while (1) {
prev_task = os_task_info_get_next(prev_task, &oti);
if (prev_task == NULL) {
break;
}
g_err |= cbor_encode_text_stringz(&tasks, oti.oti_name);
g_err |= cbor_encoder_create_map(&tasks, &task, CborIndefiniteLength);
g_err |= cbor_encode_text_stringz(&task, "prio");
g_err |= cbor_encode_uint(&task, oti.oti_prio);
g_err |= cbor_encode_text_stringz(&task, "tid");
g_err |= cbor_encode_uint(&task, oti.oti_taskid);
g_err |= cbor_encode_text_stringz(&task, "state");
g_err |= cbor_encode_uint(&task, oti.oti_state);
g_err |= cbor_encode_text_stringz(&task, "stkuse");
g_err |= cbor_encode_uint(&task, oti.oti_stkusage);
g_err |= cbor_encode_text_stringz(&task, "stksiz");
g_err |= cbor_encode_uint(&task, oti.oti_stksize);
g_err |= cbor_encode_text_stringz(&task, "cswcnt");
g_err |= cbor_encode_uint(&task, oti.oti_cswcnt);
g_err |= cbor_encode_text_stringz(&task, "runtime");
g_err |= cbor_encode_uint(&task, oti.oti_runtime);
g_err |= cbor_encode_text_stringz(&task, "last_checkin");
g_err |= cbor_encode_uint(&task, oti.oti_last_checkin);
g_err |= cbor_encode_text_stringz(&task, "next_checkin");
g_err |= cbor_encode_uint(&task, oti.oti_next_checkin);
g_err |= cbor_encoder_close_container(&tasks, &task);
}
g_err |= cbor_encoder_close_container(&cb->encoder, &tasks);
if (g_err) {
return MGMT_ERR_ENOMEM;
}
return (0);
}
static int
nmgr_def_mpstat_read(struct mgmt_cbuf *cb)
{
struct os_mempool *prev_mp;
struct os_mempool_info omi;
CborError g_err = CborNoError;
CborEncoder pools;
CborEncoder pool;
g_err |= cbor_encode_text_stringz(&cb->encoder, "rc");
g_err |= cbor_encode_int(&cb->encoder, MGMT_ERR_EOK);
g_err |= cbor_encode_text_stringz(&cb->encoder, "mpools");
g_err |= cbor_encoder_create_map(&cb->encoder, &pools,
CborIndefiniteLength);
prev_mp = NULL;
while (1) {
prev_mp = os_mempool_info_get_next(prev_mp, &omi);
if (prev_mp == NULL) {
break;
}
g_err |= cbor_encode_text_stringz(&pools, omi.omi_name);
g_err |= cbor_encoder_create_map(&pools, &pool, CborIndefiniteLength);
g_err |= cbor_encode_text_stringz(&pool, "blksiz");
g_err |= cbor_encode_uint(&pool, omi.omi_block_size);
g_err |= cbor_encode_text_stringz(&pool, "nblks");
g_err |= cbor_encode_uint(&pool, omi.omi_num_blocks);
g_err |= cbor_encode_text_stringz(&pool, "nfree");
g_err |= cbor_encode_uint(&pool, omi.omi_num_free);
g_err |= cbor_encode_text_stringz(&pool, "min");
g_err |= cbor_encode_uint(&pool, omi.omi_min_free);
g_err |= cbor_encoder_close_container(&pools, &pool);
}
g_err |= cbor_encoder_close_container(&cb->encoder, &pools);
if (g_err) {
return MGMT_ERR_ENOMEM;
}
return (0);
}
static int
nmgr_datetime_get(struct mgmt_cbuf *cb)
{
struct os_timeval tv;
struct os_timezone tz;
char buf[DATETIME_BUFSIZE];
int rc;
CborError g_err = CborNoError;
g_err |= cbor_encode_text_stringz(&cb->encoder, "rc");
g_err |= cbor_encode_int(&cb->encoder, MGMT_ERR_EOK);
/* Display the current datetime */
rc = os_gettimeofday(&tv, &tz);
assert(rc == 0);
rc = datetime_format(&tv, &tz, buf, DATETIME_BUFSIZE);
if (rc) {
rc = MGMT_ERR_EINVAL;
goto err;
}
g_err |= cbor_encode_text_stringz(&cb->encoder, "datetime");
g_err |= cbor_encode_text_stringz(&cb->encoder, buf);
if (g_err) {
return MGMT_ERR_ENOMEM;
}
return 0;
err:
return (rc);
}
static int
nmgr_datetime_set(struct mgmt_cbuf *cb)
{
struct os_timeval tv;
struct os_timezone tz;
char buf[DATETIME_BUFSIZE];
int rc = 0;
const struct cbor_attr_t datetime_write_attr[] = {
[0] = {
.attribute = "datetime",
.type = CborAttrTextStringType,
.addr.string = buf,
.len = sizeof(buf),
},
{ 0 },
};
rc = cbor_read_object(&cb->it, datetime_write_attr);
if (rc) {
return MGMT_ERR_EINVAL;
}
/* Set the current datetime */
rc = datetime_parse(buf, &tv, &tz);
if (!rc) {
rc = os_settimeofday(&tv, &tz);
if (rc) {
return MGMT_ERR_EINVAL;
}
} else {
return MGMT_ERR_EINVAL;
}
rc = mgmt_cbuf_setoerr(cb, 0);
if (rc != 0) {
return rc;
}
return 0;
}
static void
nmgr_reset_tmo(struct os_event *ev)
{
/*
* Tickle watchdog just before re-entering bootloader.
* Depending on what system has been doing lately, watchdog
* timer might be close to firing.
*/
hal_watchdog_tickle();
hal_system_reset();
}
static int
nmgr_reset(struct mgmt_cbuf *cb)
{
#if MYNEWT_VAL(LOG_SOFT_RESET)
struct log_reboot_info info;
#endif
int rc;
os_callout_init(&nmgr_reset_callout, mgmt_evq_get(), nmgr_reset_tmo, NULL);
#if MYNEWT_VAL(LOG_SOFT_RESET)
info = (struct log_reboot_info) {
.reason = HAL_RESET_REQUESTED,
.file = NULL,
.line = 0,
.pc = 0,
};
log_reboot(&info);
#endif
os_callout_reset(&nmgr_reset_callout, OS_TICKS_PER_SEC / 4);
rc = mgmt_cbuf_setoerr(cb, 0);
if (rc != 0) {
return rc;
}
return 0;
}
int
nmgr_os_groups_register(void)
{
return mgmt_group_register(&nmgr_def_group);
}