This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-mcumgr.git

commit e5fcfd64b4e507b6fe1f870c09b934f00ac2da1e
Author: Christopher Collins <ccoll...@apache.org>
AuthorDate: Fri Jan 26 15:52:28 2018 -0800

    log_mgmt command handler group.
---
 cmd/CMakeLists.txt                             |   1 +
 cmd/Kconfig                                    |   1 +
 cmd/log_mgmt/CMakeLists.txt                    |   9 +
 cmd/log_mgmt/Kconfig                           |  53 +++
 cmd/log_mgmt/include/log_mgmt/log_mgmt.h       |  83 +++++
 cmd/log_mgmt/include/log_mgmt/log_mgmt_impl.h  |  48 +++
 cmd/log_mgmt/port/mynewt/src/mynewt_log_mgmt.c | 206 +++++++++++
 cmd/log_mgmt/port/zephyr/src/zephyr_log_mgmt.c | 189 ++++++++++
 cmd/log_mgmt/src/log_mgmt.c                    | 494 +++++++++++++++++++++++++
 cmd/log_mgmt/src/log_mgmt_config.h             |  45 +++
 cmd/log_mgmt/src/stubs.c                       |  65 ++++
 cmd/os_mgmt/port/zephyr/src/zephyr_os_mgmt.c   |   2 +
 12 files changed, 1196 insertions(+)

diff --git a/cmd/CMakeLists.txt b/cmd/CMakeLists.txt
index bc91e2f..be26ded 100644
--- a/cmd/CMakeLists.txt
+++ b/cmd/CMakeLists.txt
@@ -1,3 +1,4 @@
 add_subdirectory_ifdef(CONFIG_MCUMGR_CMD_FS_MGMT   fs_mgmt)
 add_subdirectory_ifdef(CONFIG_MCUMGR_CMD_IMG_MGMT  img_mgmt)
+add_subdirectory_ifdef(CONFIG_MCUMGR_CMD_LOG_MGMT  log_mgmt)
 add_subdirectory_ifdef(CONFIG_MCUMGR_CMD_OS_MGMT   os_mgmt)
diff --git a/cmd/Kconfig b/cmd/Kconfig
index a0e2031..ea51804 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -19,6 +19,7 @@ menu "Command handlers"
 
 source "ext/mcumgr/cmd/fs_mgmt/Kconfig"
 source "ext/mcumgr/cmd/img_mgmt/Kconfig"
+source "ext/mcumgr/cmd/log_mgmt/Kconfig"
 source "ext/mcumgr/cmd/os_mgmt/Kconfig"
 
 endmenu
diff --git a/cmd/log_mgmt/CMakeLists.txt b/cmd/log_mgmt/CMakeLists.txt
new file mode 100644
index 0000000..7d72dcd
--- /dev/null
+++ b/cmd/log_mgmt/CMakeLists.txt
@@ -0,0 +1,9 @@
+target_include_directories(MCUMGR INTERFACE 
+    include
+)
+
+zephyr_library_sources(
+    cmd/log_mgmt/port/zephyr/src/zephyr_log_mgmt.c
+    cmd/log_mgmt/src/log_mgmt.c
+    cmd/log_mgmt/src/stubs.c
+)
diff --git a/cmd/log_mgmt/Kconfig b/cmd/log_mgmt/Kconfig
new file mode 100644
index 0000000..e949aa6
--- /dev/null
+++ b/cmd/log_mgmt/Kconfig
@@ -0,0 +1,53 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE log
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this log
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this log 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.
+
+menuconfig MCUMGR_CMD_LOG_MGMT
+    bool
+    prompt "Enable mcumgr handlers for log management"
+    default n
+    help
+      Enables mcumgr handlers for log management
+
+if MCUMGR_CMD_LOG_MGMT
+config LOG_MGMT_CHUNK_SIZE
+    int
+    prompt "Maximum chunk size for log downloads"
+    default 512
+    help
+      Limits the maximum chunk size in log downloads.  A buffer of this size
+      gets allocated on the stack during handling of the log show command.
+
+config LOG_MGMT_NAME_LEN
+    int
+    prompt "Maximum log name length"
+    default 64
+    help
+      Limits the maximum length of log names.  If a log's name length exceeds
+      this number, it gets truncated in management responses.  A buffer of this
+      size gets allocated on the stack during handling of all log management
+      commands.
+
+config LOG_MGMT_BODY_LEN
+    int
+    prompt "Maximum log body length"
+    default 128
+    help
+      Limits the maximum length of log entry bodies.  If a log entry's body
+      length exceeds this number, it gets truncated in management responses.  A
+      buffer of this size gets allocated on the stack during handling of the
+      log show command.
+endif
diff --git a/cmd/log_mgmt/include/log_mgmt/log_mgmt.h 
b/cmd/log_mgmt/include/log_mgmt/log_mgmt.h
new file mode 100644
index 0000000..01df2e5
--- /dev/null
+++ b/cmd/log_mgmt/include/log_mgmt/log_mgmt.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#ifndef H_LOG_MGMT_
+#define H_LOG_MGMT_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Command IDs for log management group.
+ */
+#define LOG_MGMT_ID_SHOW        0
+#define LOG_MGMT_ID_CLEAR       1
+#define LOG_MGMT_ID_APPEND      2
+#define LOG_MGMT_ID_MODULE_LIST 3
+#define LOG_MGMT_ID_LEVEL_LIST  4
+#define LOG_MGMT_ID_LOGS_LIST   5
+
+/** @brief Log output is streamed without retention (e.g., console). */
+#define LOG_MGMT_TYPE_STREAM     0
+
+/** @brief Log entries are stored in RAM. */
+#define LOG_MGMT_TYPE_MEMORY     1
+
+/** @brief Log entries are persisted across reboots. */
+#define LOG_MGMT_TYPE_STORAGE    2
+
+/** @brief Generic descriptor for an OS-specific log. */
+struct log_mgmt_log {
+    const char *name;
+    int type;
+};
+
+/** @brief Generic descriptor for an OS-specific log entry. */
+struct log_mgmt_entry {
+    int64_t ts;
+    uint32_t index;
+    const void *data;
+    size_t len;
+    uint8_t module;
+    uint8_t level;
+};
+
+/** @brief Indicates which log entries to operate on. */
+struct log_mgmt_filter {
+    /* If   min_timestamp == -1: Only access last log entry;
+     * Elif min_timestamp == 0:  Don't filter by timestamp;
+     * Else:                     Only access entries whose ts >= min_timestamp.
+     */
+    int64_t min_timestamp;
+
+    /* Only access entries whose index >= min_index. */
+    uint32_t min_index;
+};
+
+/**
+ * @brief Registers the log management command handler group.
+ */ 
+void log_mgmt_register_group(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cmd/log_mgmt/include/log_mgmt/log_mgmt_impl.h 
b/cmd/log_mgmt/include/log_mgmt/log_mgmt_impl.h
new file mode 100644
index 0000000..1890643
--- /dev/null
+++ b/cmd/log_mgmt/include/log_mgmt/log_mgmt_impl.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#ifndef H_LOG_MGMT_IMPL_
+#define H_LOG_MGMT_IMPL_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct log_mgmt_filter;
+struct log_mgmt_entry;
+struct log_mgmt_log;
+
+typedef int log_mgmt_foreach_entry_fn(const struct log_mgmt_entry *entry,
+                                      void *arg);
+
+int log_mgmt_impl_get_log(int idx, struct log_mgmt_log *out_log);
+int log_mgmt_impl_get_module(int idx, const char **out_module_name);
+int log_mgmt_impl_get_level(int idx, const char **out_level_name);
+int log_mgmt_impl_get_next_idx(uint32_t *out_idx);
+int log_mgmt_impl_foreach_entry(const char *log_name,
+                                const struct log_mgmt_filter *filter,
+                                log_mgmt_foreach_entry_fn *cb,
+                                void *arg);
+int log_mgmt_impl_clear(const char *log_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/cmd/log_mgmt/port/mynewt/src/mynewt_log_mgmt.c 
b/cmd/log_mgmt/port/mynewt/src/mynewt_log_mgmt.c
new file mode 100644
index 0000000..f81e591
--- /dev/null
+++ b/cmd/log_mgmt/port/mynewt/src/mynewt_log_mgmt.c
@@ -0,0 +1,206 @@
+/*
+ * 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 "log/log.h"
+#include "mgmt/mgmt.h"
+#include "log_mgmt/log_mgmt.h"
+#include "log_mgmt/log_mgmt_impl.h"
+#include "../../../src/log_mgmt_config.h"
+
+struct mynewt_log_mgmt_walk_arg {
+    log_mgmt_foreach_entry_fn *cb;
+    uint8_t body[LOG_MGMT_BODY_LEN];
+    void *arg;
+};
+
+static struct log *
+mynewt_log_mgmt_find_log(const char *log_name)
+{
+    struct log *log;
+
+    log = NULL;
+    while (1) {
+        log = log_list_get_next(log);
+        if (log == NULL) {
+            return NULL;
+        }
+
+        if (strcmp(log->l_name, log_name) == 0) {
+            return log;
+        }
+    }
+}
+
+int
+log_mgmt_impl_get_log(int idx, struct log_mgmt_log *out_log)
+{
+    struct log *log;
+    int i;
+
+    log = NULL;
+    for (i = 0; i <= idx; i++) {
+        log = log_list_get_next(log);
+        if (log == NULL) {
+            return MGMT_ERR_ENOENT;
+        }
+    }
+
+    out_log->name = log->l_name;
+    out_log->type = log->l_handler->type;
+    return 0;
+}
+
+int
+log_mgmt_impl_get_module(int idx, const char **out_module_name)
+{
+    const char *name;
+
+    name = LOG_MODULE_STR(idx);
+    if (name == NULL) {
+        return MGMT_ERR_ENOENT;
+    } else {
+        *out_module_name = name;
+        return 0;
+    }
+}
+
+int
+log_mgmt_impl_get_level(int idx, const char **out_level_name)
+{
+    const char *name;
+
+    name = LOG_LEVEL_STR(idx);
+    if (name == NULL) {
+        return MGMT_ERR_ENOENT;
+    } else {
+        *out_level_name = name;
+        return 0;
+    }
+}
+
+int
+log_mgmt_impl_get_next_idx(uint32_t *out_idx)
+{
+    *out_idx = g_log_info.li_next_index;
+    return 0;
+}
+
+static int
+mynewt_log_mgmt_walk_cb(struct log *log, struct log_offset *log_offset,
+                        const void *desciptor, uint16_t len)
+{
+    struct mynewt_log_mgmt_walk_arg *mynewt_log_mgmt_walk_arg;
+    struct log_mgmt_entry entry;
+    struct log_entry_hdr ueh;
+    int read_len;
+    int rc;
+
+    mynewt_log_mgmt_walk_arg = log_offset->lo_arg;
+
+    rc = log_read(log, desciptor, &ueh, 0, sizeof ueh);
+    if (rc != sizeof ueh) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    /* If specified timestamp is nonzero, it is the primary criterion, and the
+     * specified index is the secondary criterion.  If specified timetsamp is
+     * zero, specified index is the only criterion.
+     *
+     * If specified timestamp == 0: encode entries whose index >=
+     *     specified index.
+     * Else: encode entries whose timestamp >= specified timestamp and whose
+     *      index >= specified index
+     */
+
+    if (log_offset->lo_ts == 0) {
+        if (log_offset->lo_index > ueh.ue_index) {
+            return 0;
+        }
+    } else if (ueh.ue_ts < log_offset->lo_ts   ||
+               (ueh.ue_ts == log_offset->lo_ts &&
+                ueh.ue_index < log_offset->lo_index)) {
+        return 0;
+    }
+
+    read_len = min(len - sizeof ueh, LOG_MGMT_BODY_LEN - sizeof ueh);
+    rc = log_read(log, desciptor, mynewt_log_mgmt_walk_arg->body, sizeof ueh,
+                  read_len);
+    if (rc < 0) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    entry.ts = ueh.ue_ts;
+    entry.index = ueh.ue_index;
+    entry.module = ueh.ue_module;
+    entry.level = ueh.ue_level;
+    entry.len = rc;
+    entry.data = mynewt_log_mgmt_walk_arg->body;
+
+    return mynewt_log_mgmt_walk_arg->cb(&entry, mynewt_log_mgmt_walk_arg->arg);
+}
+
+int
+log_mgmt_impl_foreach_entry(const char *log_name,
+                            const struct log_mgmt_filter *filter,
+                            log_mgmt_foreach_entry_fn *cb, void *arg)
+{
+    struct mynewt_log_mgmt_walk_arg walk_arg;
+    struct log_offset offset;
+    struct log *log;
+
+    walk_arg = (struct mynewt_log_mgmt_walk_arg) {
+        .cb = cb,
+        .arg = arg,
+    };
+
+    log = mynewt_log_mgmt_find_log(log_name);
+    if (log == NULL) {
+        return MGMT_ERR_ENOENT;
+    }
+
+    if (strcmp(log->l_name, log_name) == 0) {
+        offset.lo_arg = &walk_arg;
+        offset.lo_ts = filter->min_timestamp;
+        offset.lo_index = filter->min_index;
+        offset.lo_data_len = 0;
+
+        return log_walk(log, mynewt_log_mgmt_walk_cb, &offset);
+    }
+
+    return MGMT_ERR_ENOENT;
+}
+
+int
+log_mgmt_impl_clear(const char *log_name)
+{
+    struct log *log;
+    int rc;
+
+    log = mynewt_log_mgmt_find_log(log_name);
+    if (log == NULL) {
+        return MGMT_ERR_ENOENT;
+    }
+
+    rc = log_flush(log);
+    if (rc != 0) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    return 0;
+}
diff --git a/cmd/log_mgmt/port/zephyr/src/zephyr_log_mgmt.c 
b/cmd/log_mgmt/port/zephyr/src/zephyr_log_mgmt.c
new file mode 100644
index 0000000..41cf51e
--- /dev/null
+++ b/cmd/log_mgmt/port/zephyr/src/zephyr_log_mgmt.c
@@ -0,0 +1,189 @@
+/*
+ * 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 <misc/util.h>
+#include "logging/mdlog.h"
+#include "mgmt/mgmt.h"
+#include "log_mgmt/log_mgmt.h"
+#include "log_mgmt/log_mgmt_impl.h"
+#include "../../../src/log_mgmt_config.h"
+
+struct zephyr_log_mgmt_walk_arg {
+    log_mgmt_foreach_entry_fn *cb;
+    uint8_t body[LOG_MGMT_BODY_LEN];
+    void *arg;
+};
+
+int
+log_mgmt_impl_get_log(int idx, struct log_mgmt_log *out_log)
+{
+    struct mdlog *mdlog;
+    int i;
+
+    mdlog = NULL;
+    for (i = 0; i <= idx; i++) {
+        mdlog = mdlog_get_next(mdlog);
+        if (mdlog == NULL) {
+            return MGMT_ERR_ENOENT;
+        }
+    }
+
+    out_log->name = mdlog->l_name;
+    out_log->type = mdlog->l_handler->type;
+    return 0;
+}
+
+int
+log_mgmt_impl_get_module(int idx, const char **out_module_name)
+{
+    const char *name;
+
+    name = mdlog_module_name(idx);
+    if (name == NULL) {
+        return MGMT_ERR_ENOENT;
+    } else {
+        *out_module_name = name;
+        return 0;
+    }
+}
+
+int
+log_mgmt_impl_get_level(int idx, const char **out_level_name)
+{
+    const char *name;
+
+    name = mdlog_level_name(idx);
+    if (name == NULL) {
+        return MGMT_ERR_ENOENT;
+    } else {
+        *out_level_name = name;
+        return 0;
+    }
+}
+
+int
+log_mgmt_impl_get_next_idx(uint32_t *out_idx)
+{
+    *out_idx = mdlog_get_next_index();
+    return 0;
+}
+
+static int
+zephyr_log_mgmt_walk_cb(struct mdlog *log, struct mdlog_offset *log_offset,
+                        const void *desciptor, uint16_t len)
+{
+    struct zephyr_log_mgmt_walk_arg *zephyr_log_mgmt_walk_arg;
+    struct log_mgmt_entry entry;
+    struct mdlog_entry_hdr ueh;
+    int read_len;
+    int rc;
+
+    zephyr_log_mgmt_walk_arg = log_offset->lo_arg;
+
+    rc = mdlog_read(log, desciptor, &ueh, 0, sizeof ueh);
+    if (rc != sizeof ueh) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    /* If specified timestamp is nonzero, it is the primary criterion, and the
+     * specified index is the secondary criterion.  If specified timetsamp is
+     * zero, specified index is the only criterion.
+     *
+     * If specified timestamp == 0: encode entries whose index >=
+     *     specified index.
+     * Else: encode entries whose timestamp >= specified timestamp and whose
+     *      index >= specified index
+     */
+
+    if (log_offset->lo_ts == 0) {
+        if (log_offset->lo_index > ueh.ue_index) {
+            return 0;
+        }
+    } else if (ueh.ue_ts < log_offset->lo_ts   ||
+               (ueh.ue_ts == log_offset->lo_ts &&
+                ueh.ue_index < log_offset->lo_index)) {
+        return 0;
+    }
+
+    read_len = min(len - sizeof ueh, LOG_MGMT_BODY_LEN - sizeof ueh);
+    rc = mdlog_read(log, desciptor, zephyr_log_mgmt_walk_arg->body, sizeof ueh,
+                    read_len);
+    if (rc < 0) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    entry.ts = ueh.ue_ts;
+    entry.index = ueh.ue_index;
+    entry.module = ueh.ue_module;
+    entry.level = ueh.ue_level;
+    entry.len = rc;
+    entry.data = zephyr_log_mgmt_walk_arg->body;
+
+    return zephyr_log_mgmt_walk_arg->cb(&entry, zephyr_log_mgmt_walk_arg->arg);
+}
+
+int
+log_mgmt_impl_foreach_entry(const char *log_name,
+                            const struct log_mgmt_filter *filter,
+                            log_mgmt_foreach_entry_fn *cb, void *arg)
+{
+    struct zephyr_log_mgmt_walk_arg walk_arg;
+    struct mdlog_offset offset;
+    struct mdlog *mdlog;
+
+    walk_arg = (struct zephyr_log_mgmt_walk_arg) {
+        .cb = cb,
+        .arg = arg,
+    };
+
+    mdlog = mdlog_find(log_name);
+    if (mdlog == NULL) {
+        return MGMT_ERR_ENOENT;
+    }
+
+    if (strcmp(mdlog->l_name, log_name) == 0) {
+        offset.lo_arg = &walk_arg;
+        offset.lo_ts = filter->min_timestamp;
+        offset.lo_index = filter->min_index;
+        offset.lo_data_len = 0;
+
+        return mdlog_walk(mdlog, zephyr_log_mgmt_walk_cb, &offset);
+    }
+
+    return MGMT_ERR_ENOENT;
+}
+
+int
+log_mgmt_impl_clear(const char *log_name)
+{
+    struct mdlog *mdlog;
+    int rc;
+
+    mdlog = mdlog_find(log_name);
+    if (mdlog == NULL) {
+        return MGMT_ERR_ENOENT;
+    }
+
+    rc = mdlog_flush(mdlog);
+    if (rc != 0) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    return 0;
+}
diff --git a/cmd/log_mgmt/src/log_mgmt.c b/cmd/log_mgmt/src/log_mgmt.c
new file mode 100644
index 0000000..430f35a
--- /dev/null
+++ b/cmd/log_mgmt/src/log_mgmt.c
@@ -0,0 +1,494 @@
+/*
+ * 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 <stdio.h>
+
+#include "mgmt/mgmt.h"
+#include "cborattr/cborattr.h"
+#include "cbor_cnt_writer.h"
+#include "log_mgmt/log_mgmt.h"
+#include "log_mgmt/log_mgmt_impl.h"
+#include "log_mgmt_config.h"
+
+/** Context used during walks. */
+struct log_walk_ctxt {
+    /* The number of bytes encoded to the response so far. */
+    size_t rsp_len;
+
+    /* The encoder to use to write the current log entry. */
+    struct CborEncoder *enc;
+};
+
+static mgmt_handler_fn log_mgmt_show;
+static mgmt_handler_fn log_mgmt_clear;
+static mgmt_handler_fn log_mgmt_module_list;
+static mgmt_handler_fn log_mgmt_level_list;
+static mgmt_handler_fn log_mgmt_logs_list;
+
+static struct mgmt_handler log_mgmt_handlers[] = {
+    [LOG_MGMT_ID_SHOW] =        { log_mgmt_show, NULL },
+    [LOG_MGMT_ID_CLEAR] =       { NULL, log_mgmt_clear },
+    [LOG_MGMT_ID_MODULE_LIST] = { log_mgmt_module_list, NULL },
+    [LOG_MGMT_ID_LEVEL_LIST] =  { log_mgmt_level_list, NULL },
+    [LOG_MGMT_ID_LOGS_LIST] =   { log_mgmt_logs_list, NULL },
+};
+
+#define LOG_MGMT_HANDLER_CNT \
+    sizeof log_mgmt_handlers / sizeof log_mgmt_handlers[0]
+
+static struct mgmt_group log_mgmt_group = {
+    .mg_handlers = log_mgmt_handlers,
+    .mg_handlers_count = LOG_MGMT_HANDLER_CNT,
+    .mg_group_id = MGMT_GROUP_ID_LOG,
+};
+
+static int
+log_mgmt_encode_entry(CborEncoder *enc, const struct log_mgmt_entry *entry,
+                      size_t *out_len)
+{
+    CborEncoder entry_enc;
+    CborError err;
+
+    err = 0;
+    err |= cbor_encoder_create_map(enc, &entry_enc, 5);
+    err |= cbor_encode_text_stringz(&entry_enc, "msg");
+    err |= cbor_encode_byte_string(&entry_enc, entry->data, entry->len);
+    err |= cbor_encode_text_stringz(&entry_enc, "ts");
+    err |= cbor_encode_int(&entry_enc, entry->ts);
+    err |= cbor_encode_text_stringz(&entry_enc, "level");
+    err |= cbor_encode_uint(&entry_enc, entry->level);
+    err |= cbor_encode_text_stringz(&entry_enc, "index");
+    err |= cbor_encode_uint(&entry_enc, entry->index);
+    err |= cbor_encode_text_stringz(&entry_enc, "module");
+    err |= cbor_encode_uint(&entry_enc, entry->module);
+    err |= cbor_encoder_close_container(enc, &entry_enc);
+
+    if (err != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    if (out_len != NULL) {
+        *out_len = cbor_encode_bytes_written(enc);
+    }
+
+    return 0;
+}
+
+static int
+log_mgmt_walk_cb_encode(const struct log_mgmt_entry *entry, void *arg)
+{
+    struct CborCntWriter cnt_writer;
+    struct log_walk_ctxt *ctxt;
+    CborEncoder cnt_encoder;
+    size_t entry_len;
+    int rc;
+
+    ctxt = arg;
+
+    /*** First, determine if this entry would fit. */
+
+    cbor_cnt_writer_init(&cnt_writer);
+    cbor_encoder_cust_writer_init(&cnt_encoder, &cnt_writer.enc, 0);
+    rc = log_mgmt_encode_entry(&cnt_encoder, entry, &entry_len);
+    if (rc != 0) {
+        return rc;
+    }
+
+    /* `+ 1` to account for the CBOR array terminator. */
+    if (ctxt->rsp_len + entry_len + 1 > LOG_MGMT_CHUNK_SIZE) {
+        return MGMT_ERR_EMSGSIZE;
+    }
+    ctxt->rsp_len += entry_len;
+
+    /*** The entry fits.  Now encode it. */
+
+    rc = log_mgmt_encode_entry(ctxt->enc, entry, NULL);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+static int
+log_encode_entries(const struct log_mgmt_log *log, CborEncoder *enc,
+                   int64_t timestamp, uint32_t index)
+{
+    struct log_mgmt_filter filter;
+    struct log_walk_ctxt ctxt;
+    CborEncoder entries;
+    CborError err;
+    int rc;
+
+    err = 0;
+    err |= cbor_encode_text_stringz(enc, "entries");
+    err |= cbor_encoder_create_array(enc, &entries, CborIndefiniteLength);
+
+    filter = (struct log_mgmt_filter) {
+        .min_timestamp = timestamp,
+        .min_index = index,
+    };
+    ctxt = (struct log_walk_ctxt) {
+        .enc = &entries,
+        .rsp_len = cbor_encode_bytes_written(enc),
+    };
+
+    rc = log_mgmt_impl_foreach_entry(log->name, &filter,
+                                     log_mgmt_walk_cb_encode, &ctxt);
+    if (rc != 0 && rc != MGMT_ERR_EMSGSIZE) {
+        return rc;
+    }
+
+    err |= cbor_encoder_close_container(enc, &entries);
+
+    if (err != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    return 0;
+}
+
+static int
+log_encode(const struct log_mgmt_log *log, CborEncoder *ctxt,
+           int64_t timestamp, uint32_t index)
+{
+    CborEncoder logs;
+    CborError err;
+    int rc;
+
+    err = 0;
+    err |= cbor_encoder_create_map(ctxt, &logs, CborIndefiniteLength);
+    err |= cbor_encode_text_stringz(&logs, "name");
+    err |= cbor_encode_text_stringz(&logs, log->name);
+    err |= cbor_encode_text_stringz(&logs, "type");
+    err |= cbor_encode_uint(&logs, log->type);
+
+    rc = log_encode_entries(log, &logs, timestamp, index);
+    if (rc != 0) {
+        return rc;
+    }
+
+    err |= cbor_encoder_close_container(ctxt, &logs);
+
+    if (err != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    return 0;
+}
+
+/**
+ * Command handler: log show
+ */
+static int
+log_mgmt_show(struct mgmt_ctxt *ctxt)
+{
+    char name[LOG_MGMT_NAME_LEN];
+    struct log_mgmt_log log;
+    CborEncoder logs;
+    CborError err;
+    uint64_t index;
+    int64_t timestamp;
+    uint32_t next_idx;
+    int name_len;
+    int log_idx;
+    int rc;
+
+    const struct cbor_attr_t attr[] = {
+        {
+            .attribute = "log_name",
+            .type = CborAttrTextStringType,
+            .addr.string = name,
+            .len = sizeof(name),
+        },
+        {
+            .attribute = "ts",
+            .type = CborAttrIntegerType,
+            .addr.integer = &timestamp,
+        },
+        {
+            .attribute = "index",
+            .type = CborAttrUnsignedIntegerType,
+            .addr.uinteger = &index,
+        },
+        {
+            .attribute = NULL,
+        },
+    };
+
+    name[0] = '\0';
+    rc = cbor_read_object(&ctxt->it, attr);
+    if (rc != 0) {
+        return MGMT_ERR_EINVAL;
+    }
+    name_len = strlen(name);
+
+    /* Determine the index that the next log entry would use. */
+    rc = log_mgmt_impl_get_next_idx(&next_idx);
+    if (rc != 0) {
+        return MGMT_ERR_EUNKNOWN;
+    }
+
+    err = 0;
+    err |= cbor_encode_text_stringz(&ctxt->encoder, "next_index");
+    err |= cbor_encode_uint(&ctxt->encoder, next_idx);
+
+    err |= cbor_encode_text_stringz(&ctxt->encoder, "logs");
+    err |= cbor_encoder_create_array(&ctxt->encoder, &logs,
+                                     CborIndefiniteLength);
+
+    /* Iterate list of logs, encoding each that matches the client request. */
+    for (log_idx = 0; ; log_idx++) {
+        rc = log_mgmt_impl_get_log(log_idx, &log);
+        if (rc == MGMT_ERR_ENOENT) {
+            /* Log list fully iterated. */
+            if (name_len != 0) {
+                /* Client specified log name, but the log wasn't found. */
+                return MGMT_ERR_ENOENT;
+            } else {
+                break;
+            }
+        } else if (rc != 0) {
+            return rc;
+        }
+
+        /* Stream logs cannot be read. */
+        if (log.type != LOG_MGMT_TYPE_STREAM) {
+            if (name_len == 0 || strcmp(name, log.name) == 0) {
+                rc = log_encode(&log, &logs, timestamp, index);
+                if (rc != 0) {
+                    return rc;
+                }
+
+                /* If the client specified this log, he isn't interested in the
+                 * remaining ones.
+                 */
+                if (name_len != 0) {
+                    break;
+                }
+            }
+        }
+    }
+
+    err |= cbor_encoder_close_container(&ctxt->encoder, &logs);
+    err |= cbor_encode_text_stringz(&ctxt->encoder, "rc");
+    err |= cbor_encode_int(&ctxt->encoder, rc);
+
+    if (err != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    return 0;
+}
+
+/**
+ * Command handler: log module_list
+ */
+static int
+log_mgmt_module_list(struct mgmt_ctxt *ctxt)
+{
+    const char *module_name;
+    CborEncoder modules;
+    CborError err;
+    int module;
+    int rc;
+
+    err = 0;
+    err |= cbor_encode_text_stringz(&ctxt->encoder, "rc");
+    err |= cbor_encode_int(&ctxt->encoder, MGMT_ERR_EOK);
+    err |= cbor_encode_text_stringz(&ctxt->encoder, "module_map");
+    err |= cbor_encoder_create_map(&ctxt->encoder, &modules,
+                                   CborIndefiniteLength);
+
+    for (module = 0; ; module++) {
+        rc = log_mgmt_impl_get_module(module, &module_name);
+        if (rc == MGMT_ERR_ENOENT) {
+            break;
+        }
+        if (rc != 0) {
+            return rc;
+        }
+
+        if (module_name != NULL) {
+            err |= cbor_encode_text_stringz(&modules, module_name);
+            err |= cbor_encode_uint(&modules, module);
+        }
+    }
+
+    err |= cbor_encoder_close_container(&ctxt->encoder, &modules);
+
+    if (err != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    return 0;
+}
+
+/**
+ * Command handler: log list
+ */
+static int
+log_mgmt_logs_list(struct mgmt_ctxt *ctxt)
+{
+    struct log_mgmt_log log;
+    CborEncoder log_list;
+    CborError err;
+    int log_idx;
+    int rc;
+
+    err = 0;
+    err |= cbor_encode_text_stringz(&ctxt->encoder, "rc");
+    err |= cbor_encode_int(&ctxt->encoder, MGMT_ERR_EOK);
+    err |= cbor_encode_text_stringz(&ctxt->encoder, "log_list");
+    err |= cbor_encoder_create_array(&ctxt->encoder, &log_list,
+                                     CborIndefiniteLength);
+
+    for (log_idx = 0; ; log_idx++) {
+        rc = log_mgmt_impl_get_log(log_idx, &log);
+        if (rc == MGMT_ERR_ENOENT) {
+            break;
+        }
+        if (rc != 0) {
+            return rc;
+        }
+
+        if (log.type != LOG_MGMT_TYPE_STREAM) {
+            err |= cbor_encode_text_stringz(&log_list, log.name);
+        }
+    }
+
+    err |= cbor_encoder_close_container(&ctxt->encoder, &log_list);
+
+    if (err != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    return 0;
+}
+
+/**
+ * Command handler: log level_list
+ */
+static int
+log_mgmt_level_list(struct mgmt_ctxt *ctxt)
+{
+    const char *level_name;
+    CborEncoder level_map;
+    CborError err;
+    int level;
+    int rc;
+
+    err = 0;
+    err |= cbor_encode_text_stringz(&ctxt->encoder, "rc");
+    err |= cbor_encode_int(&ctxt->encoder, MGMT_ERR_EOK);
+    err |= cbor_encode_text_stringz(&ctxt->encoder, "level_map");
+    err |= cbor_encoder_create_map(&ctxt->encoder, &level_map,
+                                   CborIndefiniteLength);
+
+    for (level = 0; ; level++) {
+        rc = log_mgmt_impl_get_level(level, &level_name);
+        if (rc == MGMT_ERR_ENOENT) {
+            break;
+        }
+        if (rc != 0) {
+            return rc;
+        }
+
+        if (level_name != NULL) {
+            err |= cbor_encode_text_stringz(&level_map, level_name);
+            err |= cbor_encode_uint(&level_map, level);
+        }
+    }
+
+    err |= cbor_encoder_close_container(&ctxt->encoder, &level_map);
+
+    if (err != 0) {
+        return MGMT_ERR_ENOMEM;
+    }
+
+    return 0;
+}
+
+/**
+ * Command handler: log clear
+ */
+static int
+log_mgmt_clear(struct mgmt_ctxt *ctxt)
+{
+    struct log_mgmt_log log;
+    char name[LOG_MGMT_NAME_LEN] = {0};
+    int name_len;
+    int log_idx;
+    int rc;
+
+    const struct cbor_attr_t attr[] = {
+        {
+            .attribute = "log_name",
+            .type = CborAttrTextStringType,
+            .addr.string = name,
+            .len = sizeof(name)
+        },
+        {
+            .attribute = NULL
+        },
+    };
+
+    name[0] = '\0';
+    rc = cbor_read_object(&ctxt->it, attr);
+    if (rc != 0) {
+        return MGMT_ERR_EINVAL;
+    }
+    name_len = strlen(name);
+
+    for (log_idx = 0; ; log_idx++) {
+        rc = log_mgmt_impl_get_log(log_idx, &log);
+        if (rc == MGMT_ERR_ENOENT) {
+            return 0;
+        }
+        if (rc != 0) {
+            return rc;
+        }
+
+        if (log.type != LOG_MGMT_TYPE_STREAM) {
+            if (name_len == 0 || strcmp(log.name, name) == 0) {
+                rc = log_mgmt_impl_clear(log.name);
+                if (rc != 0) {
+                    return rc;
+                }
+
+                if (name_len != 0) {
+                    return 0;
+                }
+            }
+        }
+    }
+
+    if (name_len != 0) {
+        return MGMT_ERR_ENOENT;
+    }
+
+    return 0;
+}
+
+void
+log_mgmt_register_group(void)
+{
+    mgmt_register_group(&log_mgmt_group);
+}
diff --git a/cmd/log_mgmt/src/log_mgmt_config.h 
b/cmd/log_mgmt/src/log_mgmt_config.h
new file mode 100644
index 0000000..572fb00
--- /dev/null
+++ b/cmd/log_mgmt/src/log_mgmt_config.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef H_LOG_MGMT_CONFIG_
+#define H_LOG_MGMT_CONFIG_
+
+#if defined MYNEWT
+
+#include "syscfg/syscfg.h"
+
+#define LOG_MGMT_CHUNK_SIZE MYNEWT_VAL(LOG_MGMT_CHUNK_SIZE)
+#define LOG_MGMT_NAME_LEN   MYNEWT_VAL(LOG_MGMT_NAME_LEN)
+#define LOG_MGMT_BODY_LEN   MYNEWT_VAL(LOG_MGMT_BODY_LEN)
+
+#elif defined __ZEPHYR__
+
+#define LOG_MGMT_CHUNK_SIZE CONFIG_LOG_MGMT_CHUNK_SIZE
+#define LOG_MGMT_NAME_LEN   CONFIG_LOG_MGMT_NAME_LEN
+#define LOG_MGMT_BODY_LEN   CONFIG_LOG_MGMT_BODY_LEN
+
+#else
+
+/* No direct support for this OS.  The application needs to define the above
+ * settings itself.
+ */
+
+#endif
+
+#endif
diff --git a/cmd/log_mgmt/src/stubs.c b/cmd/log_mgmt/src/stubs.c
new file mode 100644
index 0000000..7ce61cf
--- /dev/null
+++ b/cmd/log_mgmt/src/stubs.c
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+/**
+ * These stubs get linked in when there is no equivalent OS-specific
+ * implementation.
+ */
+
+#include "mgmt/mgmt.h"
+#include "log_mgmt/log_mgmt_impl.h"
+
+int __attribute__((weak))
+log_mgmt_impl_get_log(int idx, struct log_mgmt_log *out_log)
+{
+    return MGMT_ERR_ENOTSUP;
+}
+
+int __attribute__((weak))
+log_mgmt_impl_get_module(int idx, const char **out_module_name)
+{
+    return MGMT_ERR_ENOTSUP;
+}
+
+int __attribute__((weak))
+log_mgmt_impl_get_level(int idx, const char **out_level_name)
+{
+    return MGMT_ERR_ENOTSUP;
+}
+
+int __attribute__((weak))
+log_mgmt_impl_get_next_idx(uint32_t *out_idx)
+{
+    return MGMT_ERR_ENOTSUP;
+}
+
+int __attribute__((weak))
+log_mgmt_impl_foreach_entry(const char *log_name,
+                            const struct log_mgmt_filter *filter,
+                            log_mgmt_foreach_entry_fn *cb,
+                            void *arg)
+{
+    return MGMT_ERR_ENOTSUP;
+}
+
+int __attribute__((weak))
+log_mgmt_impl_clear(const char *log_name)
+{
+    return MGMT_ERR_ENOTSUP;
+}
diff --git a/cmd/os_mgmt/port/zephyr/src/zephyr_os_mgmt.c 
b/cmd/os_mgmt/port/zephyr/src/zephyr_os_mgmt.c
index df996a8..20ee5a6 100644
--- a/cmd/os_mgmt/port/zephyr/src/zephyr_os_mgmt.c
+++ b/cmd/os_mgmt/port/zephyr/src/zephyr_os_mgmt.c
@@ -21,6 +21,7 @@
 #include <misc/reboot.h>
 #include <debug/object_tracing.h>
 #include <kernel_structs.h>
+#include "logging/reboot_log.h"
 #include "mgmt/mgmt.h"
 #include "os_mgmt/os_mgmt.h"
 #include "os_mgmt/os_mgmt_impl.h"
@@ -77,6 +78,7 @@ os_mgmt_impl_task_info(int idx, struct os_mgmt_task_info 
*out_info)
 static void
 zephyr_os_mgmt_reset_work_handler(struct k_work *work)
 {
+    reboot_log_write("mcumgr");
     sys_reboot(SYS_REBOOT_WARM);
 }
 

-- 
To stop receiving notification emails like this one, please contact
ccoll...@apache.org.

Reply via email to