You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2017/12/08 00:56:06 UTC
[mynewt-mcumgr] 01/02: initial commit
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 63166fd4cea4b98dea110185a5467a9612dc15f0
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Thu Dec 7 12:41:12 2017 -0800
initial commit
---
.gitignore | 37 ++
mgmt/mgmt/include/mgmt/mgmt.h | 139 ++++++++
mgmt/mgmt/pkg.yml | 28 ++
mgmt/mgmt/src/mgmt.c | 112 ++++++
mgmt/mgmt/syscfg.yml | 18 +
mgmt/newtmgr/include/newtmgr/newtmgr.h | 74 ++++
mgmt/newtmgr/nmgr_os/include/nmgr_os/nmgr_os.h | 43 +++
mgmt/newtmgr/nmgr_os/pkg.yml | 38 ++
mgmt/newtmgr/nmgr_os/src/newtmgr_os.c | 346 ++++++++++++++++++
mgmt/newtmgr/nmgr_os/syscfg.yml | 23 ++
mgmt/newtmgr/pkg.yml | 40 +++
mgmt/newtmgr/src/mynewt_nmgr.c | 182 ++++++++++
mgmt/newtmgr/src/newtmgr.c | 205 +++++++++++
.../transport/ble/include/nmgrble/newtmgr_ble.h | 42 +++
mgmt/newtmgr/transport/ble/pkg.yml | 35 ++
mgmt/newtmgr/transport/ble/src/newtmgr_ble.c | 242 +++++++++++++
mgmt/newtmgr/transport/nmgr_shell/pkg.yml | 34 ++
mgmt/newtmgr/transport/nmgr_shell/src/nmgr_shell.c | 71 ++++
mgmt/newtmgr/transport/nmgr_uart/pkg.yml | 35 ++
mgmt/newtmgr/transport/nmgr_uart/src/nmgr_uart.c | 389 +++++++++++++++++++++
mgmt/newtmgr/transport/nmgr_uart/syscfg.yml | 28 ++
21 files changed, 2161 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..91be3d8
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+.app.db
+.app
+bin
+obj
+tags
+.gdb_history
+.gdb_out
+.gdb_cmds
+.gdbinit
+*~
+.DS_Store
+*.swp
+*.swo
+*.bak
+docs/html
+docs/latex
+cscope.*
+*.tags
diff --git a/mgmt/mgmt/include/mgmt/mgmt.h b/mgmt/mgmt/include/mgmt/mgmt.h
new file mode 100644
index 0000000..0313736
--- /dev/null
+++ b/mgmt/mgmt/include/mgmt/mgmt.h
@@ -0,0 +1,139 @@
+/*
+ * 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 _MGMT_MGMT_H_
+#define _MGMT_MGMT_H_
+
+#include <inttypes.h>
+
+#include <os/queue.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* MTU for newtmgr responses */
+#define MGMT_MAX_MTU 1024
+
+#ifndef STR
+/* Stringification of constants */
+#define STR(x) #x
+#endif
+
+#define NMGR_OP_READ (0)
+#define NMGR_OP_READ_RSP (1)
+#define NMGR_OP_WRITE (2)
+#define NMGR_OP_WRITE_RSP (3)
+
+/* First 64 groups are reserved for system level newtmgr commands.
+ * Per-user commands are then defined after group 64.
+ */
+#define MGMT_GROUP_ID_DEFAULT (0)
+#define MGMT_GROUP_ID_IMAGE (1)
+#define MGMT_GROUP_ID_STATS (2)
+#define MGMT_GROUP_ID_CONFIG (3)
+#define MGMT_GROUP_ID_LOGS (4)
+#define MGMT_GROUP_ID_CRASH (5)
+#define MGMT_GROUP_ID_SPLIT (6)
+#define MGMT_GROUP_ID_RUN (7)
+#define MGMT_GROUP_ID_FS (8)
+#define MGMT_GROUP_ID_PERUSER (64)
+
+/**
+ * Newtmgr error codes
+ */
+#define MGMT_ERR_EOK (0)
+#define MGMT_ERR_EUNKNOWN (1)
+#define MGMT_ERR_ENOMEM (2)
+#define MGMT_ERR_EINVAL (3)
+#define MGMT_ERR_ETIMEOUT (4)
+#define MGMT_ERR_ENOENT (5)
+#define MGMT_ERR_EBADSTATE (6) /* Current state disallows command. */
+#define MGMT_ERR_EMSGSIZE (7) /* Response too large. */
+#define MGMT_ERR_EPERUSER (256)
+
+#define NMGR_HDR_SIZE (8)
+
+struct nmgr_hdr {
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ uint8_t nh_op:3; /* NMGR_OP_XXX */
+ uint8_t _res1:5;
+#endif
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ uint8_t _res1:5;
+ uint8_t nh_op:3; /* NMGR_OP_XXX */
+#endif
+ uint8_t nh_flags; /* XXX reserved for future flags */
+ uint16_t nh_len; /* length of the payload */
+ uint16_t nh_group; /* NMGR_GROUP_XXX */
+ uint8_t nh_seq; /* sequence number */
+ uint8_t nh_id; /* message ID within group */
+};
+
+typedef int mgmt_reader_trim_front_fn(struct cbor_decoder_reader *reader,
+ int len);
+typedef int mgmt_writer_write_at_fn(struct cbor_encoder_writer *writer,
+ int offset, const void *data, int len);
+
+/* XXX: Bad name */
+struct mgmt_cbor_cfg {
+ mgmt_reader_trim_front_fn *trim_front;
+ mgmt_writer_write_at_fn *write_at;
+
+ struct cbor_decoder_reader *reader;
+ struct cbor_encoder_writer *writer;
+};
+
+struct mgmt_cbuf {
+ struct CborEncoder encoder;
+ struct CborParser parser;
+ struct CborValue it;
+};
+
+typedef int (*mgmt_handler_func_t)(struct mgmt_cbuf *);
+
+struct mgmt_handler {
+ mgmt_handler_func_t mh_read;
+ mgmt_handler_func_t mh_write;
+};
+
+struct mgmt_group {
+ const struct mgmt_handler *mg_handlers;
+ uint16_t mg_handlers_count;
+ uint16_t mg_group_id;
+ struct mgmt_group *mg_next;
+};
+
+#define MGMT_GROUP_SET_HANDLERS(__group, __handlers) \
+ (__group)->mg_handlers = (__handlers); \
+ (__group)->mg_handlers_count = (sizeof((__handlers)) / \
+ sizeof(struct mgmt_handler));
+
+int mgmt_group_register(struct mgmt_group *group);
+int mgmt_cbuf_setoerr(struct mgmt_cbuf *njb, int errcode);
+const struct mgmt_handler *mgmt_find_handler(uint16_t group_id,
+ uint16_t handler_id);
+int mgmt_err_from_cbor(int cbor_status);
+int mgmt_cbuf_init(struct mgmt_cbuf *cbuf, struct mgmt_cbor_cfg *cfg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MGMT_MGMT_H_ */
diff --git a/mgmt/mgmt/pkg.yml b/mgmt/mgmt/pkg.yml
new file mode 100644
index 0000000..2361166
--- /dev/null
+++ b/mgmt/mgmt/pkg.yml
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+pkg.name: mgmt/mgmt
+pkg.description: System-wide management interfaces.
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - kernel/os
+ - encoding/tinycbor
diff --git a/mgmt/mgmt/src/mgmt.c b/mgmt/mgmt/src/mgmt.c
new file mode 100644
index 0000000..ab0cb8a
--- /dev/null
+++ b/mgmt/mgmt/src/mgmt.c
@@ -0,0 +1,112 @@
+/*
+ * 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 <os/os.h>
+#include <tinycbor/cbor.h>
+#include "mgmt/mgmt.h"
+
+static struct mgmt_group *mgmt_group_list;
+static struct mgmt_group *mgmt_group_list_end;
+
+void
+mgmt_group_register(struct mgmt_group *group)
+{
+ if (mgmt_group_list_end == NULL) {
+ mgmt_group_list = group;
+ } else {
+ mgmt_group_list_end->mg_next = group;
+ }
+ mgmt_group_list_end = group;
+}
+
+static struct mgmt_group *
+mgmt_find_group(uint16_t group_id)
+{
+ struct mgmt_group *group;
+
+ for (group = mgmt_group_list; group != NULL; group = group->mg_next) {
+ if (group->mg_group_id == group_id) {
+ return group;
+ }
+ }
+
+ return NULL;
+}
+
+const struct mgmt_handler *
+mgmt_find_handler(uint16_t group_id, uint16_t handler_id)
+{
+ struct mgmt_group *group;
+ const struct mgmt_handler *handler;
+
+ group = mgmt_find_group(group_id);
+ if (group == NULL) {
+ return NULL;
+ }
+
+ if (handler_id >= group->mg_handlers_count) {
+ return NULL;
+ }
+
+ return &group->mg_handlers[handler_id];
+}
+
+int
+mgmt_cbuf_setoerr(struct CborEncoder *encoder, int errcode)
+{
+ int rc;
+
+ rc = cbor_encode_text_stringz(encoder, "rc");
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = cbor_encode_int(encoder, errcode);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+mgmt_err_from_cbor(int cbor_status)
+{
+ switch (cbor_status) {
+ case CborNoError: return MGMT_ERR_EOK;
+ case CborErrorOutOfMemory: return MGMT_ERR_ENOMEM;
+ default: return MGMT_ERR_EUNKNOWN;
+ }
+}
+
+int
+mgmt_cbuf_init(struct mgmt_cbuf *cbuf, struct mgmt_cbor_cfg *cfg)
+{
+ int rc;
+
+ rc = cbor_parser_init(cfg->reader, 0, &cbuf->parser, &cbuf->it);
+ if (rc != CborNoError) {
+ return mgmt_err_from_cbor(rc);
+ }
+
+ cbor_encoder_init(&cbuf->encoder, cfg->writer, 0);
+
+ return 0;
+}
diff --git a/mgmt/mgmt/syscfg.yml b/mgmt/mgmt/syscfg.yml
new file mode 100644
index 0000000..30ccc02
--- /dev/null
+++ b/mgmt/mgmt/syscfg.yml
@@ -0,0 +1,18 @@
+#
+# 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.
+#
diff --git a/mgmt/newtmgr/include/newtmgr/newtmgr.h b/mgmt/newtmgr/include/newtmgr/newtmgr.h
new file mode 100644
index 0000000..b01d962
--- /dev/null
+++ b/mgmt/newtmgr/include/newtmgr/newtmgr.h
@@ -0,0 +1,74 @@
+/*
+ * 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 _NEWTMGR_H_
+#define _NEWTMGR_H_
+
+#include <tinycbor/cbor.h>
+#include <inttypes.h>
+#include <os/os.h>
+#include <os/endian.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nmgr_transport;
+struct mgmt_cbor_cfg;
+
+/**
+ * Transmit function. The supplied mbuf is always consumed, regardless of
+ * return code.
+ */
+typedef int (*nmgr_transport_out_func_t)(struct nmgr_transport *nt,
+ struct os_mbuf *m);
+
+/**
+ * MTU query function. The supplied mbuf should contain a request received
+ * from the peer whose MTU is being queried. This function takes an mbuf
+ * parameter because some transports store connection-specific information in
+ * the mbuf user header (e.g., the BLE transport stores the connection handle).
+ *
+ * @return The transport's MTU;
+ * 0 if transmission is currently not possible.
+ */
+//typedef uint16_t (*nmgr_transport_get_mtu_func_t)(struct os_mbuf *m);
+
+struct nmgr_transport {
+ nmgr_transport_out_func_t nt_output;
+};
+
+struct mynewt_nmgr_transport {
+ struct nmgr_transport mnt_xport;
+ struct os_mqueue mnt_imq;
+};
+
+int mynewt_nmgr_transport_init(struct mynewt_nmgr_transport *mnt,
+ nmgr_transport_out_func_t output_func);
+
+int nmgr_build_err_rsp(struct mgmt_cbor_cfg *cfg,
+ const struct nmgr_hdr *req_hdr,
+ int status);
+int nmgr_handle_single_req(struct mgmt_cbor_cfg *cfg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NETMGR_H */
diff --git a/mgmt/newtmgr/nmgr_os/include/nmgr_os/nmgr_os.h b/mgmt/newtmgr/nmgr_os/include/nmgr_os/nmgr_os.h
new file mode 100644
index 0000000..6c3460f
--- /dev/null
+++ b/mgmt/newtmgr/nmgr_os/include/nmgr_os/nmgr_os.h
@@ -0,0 +1,43 @@
+/*
+ * 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 _NMGR_OS_H_
+#define _NMGR_OS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Id's for OS group commands
+ */
+#define NMGR_ID_ECHO 0
+#define NMGR_ID_CONS_ECHO_CTRL 1
+#define NMGR_ID_TASKSTATS 2
+#define NMGR_ID_MPSTATS 3
+#define NMGR_ID_DATETIME_STR 4
+#define NMGR_ID_RESET 5
+
+int nmgr_os_groups_register(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NMGR_OS_H_ */
diff --git a/mgmt/newtmgr/nmgr_os/pkg.yml b/mgmt/newtmgr/nmgr_os/pkg.yml
new file mode 100644
index 0000000..6c39c16
--- /dev/null
+++ b/mgmt/newtmgr/nmgr_os/pkg.yml
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+
+pkg.name: mgmt/newtmgr/nmgr_os
+pkg.description: Default newtmgr command.
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - hw/hal
+ - time/datetime
+ - kernel/os
+ - mgmt/mgmt
+ - encoding/tinycbor
+ - encoding/cborattr
+
+pkg.deps.LOG_SOFT_RESET:
+ - sys/reboot
+
+pkg.req_apis:
+ - newtmgr
diff --git a/mgmt/newtmgr/nmgr_os/src/newtmgr_os.c b/mgmt/newtmgr/nmgr_os/src/newtmgr_os.c
new file mode 100644
index 0000000..b2ebc37
--- /dev/null
+++ b/mgmt/newtmgr/nmgr_os/src/newtmgr_os.c
@@ -0,0 +1,346 @@
+/*
+ * 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 <syscfg/syscfg.h>
+
+#include <os/os.h>
+#include <os/endian.h>
+
+#include <assert.h>
+#include <string.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)
+{
+ int rc;
+
+ os_callout_init(&nmgr_reset_callout, mgmt_evq_get(), nmgr_reset_tmo, NULL);
+
+#if MYNEWT_VAL(LOG_SOFT_RESET)
+ log_reboot(HAL_RESET_REQUESTED);
+#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);
+}
+
diff --git a/mgmt/newtmgr/nmgr_os/syscfg.yml b/mgmt/newtmgr/nmgr_os/syscfg.yml
new file mode 100644
index 0000000..78caaf0
--- /dev/null
+++ b/mgmt/newtmgr/nmgr_os/syscfg.yml
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+syscfg.defs:
+ LOG_SOFT_RESET:
+ description: 'Log soft restarts'
+ value: 1
diff --git a/mgmt/newtmgr/pkg.yml b/mgmt/newtmgr/pkg.yml
new file mode 100644
index 0000000..6f73873
--- /dev/null
+++ b/mgmt/newtmgr/pkg.yml
@@ -0,0 +1,40 @@
+#
+# 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.
+#
+
+pkg.name: mgmt/newtmgr
+pkg.description: Server-side newtmgr functionality.
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - encoding/cborattr
+ - kernel/os
+ - mgmt/mgmt
+ - mgmt/newtmgr/nmgr_os
+ - util/mem
+
+pkg.deps.NEWTMGR_BLE_HOST:
+ - mgmt/newtmgr/transport/ble
+
+pkg.apis:
+ - newtmgr
+
+pkg.init:
+ nmgr_pkg_init: 500
diff --git a/mgmt/newtmgr/src/mynewt_nmgr.c b/mgmt/newtmgr/src/mynewt_nmgr.c
new file mode 100644
index 0000000..cdd9eac
--- /dev/null
+++ b/mgmt/newtmgr/src/mynewt_nmgr.c
@@ -0,0 +1,182 @@
+#include "os/os.h"
+#include "mgmt/mgmt.h"
+#include "mem/mem.h"
+
+static mgmt_reader_trim_front_fn mynewt_nmgr_trim_front;
+static mgmt_reader_trim_back_fn mynewt_nmgr_trim_back;
+static mgmt_reader_write_at_fn mynewt_nmgr_write_at;
+
+static struct mgmt_cbor_cfg mynewt_nmgr_cbor_cfg = {
+ .mr.trim_front = mynewt_nmgr_trim_front,
+ .mw.trim_back = mynewt_nmgr_trim_back,
+ .mw.write_at = mynewt_nmgr_write_at,
+};
+
+/**
+ * Allocates an mbuf to contain an outgoing response fragment.
+ */
+static struct os_mbuf *
+mynewt_nmgr_rsp_frag_alloc(uint16_t frag_size, void *arg)
+{
+ struct os_mbuf *src_rsp;
+ struct os_mbuf *frag;
+
+ /* We need to duplicate the user header from the source response, as that
+ * is where transport-specific information is stored.
+ */
+ src_rsp = arg;
+
+ frag = os_msys_get_pkthdr(frag_size, OS_MBUF_USRHDR_LEN(src_rsp));
+ if (frag != NULL) {
+ /* Copy the user header from the response into the fragment mbuf. */
+ memcpy(OS_MBUF_USRHDR(frag), OS_MBUF_USRHDR(src_rsp),
+ OS_MBUF_USRHDR_LEN(src_rsp));
+ }
+
+ return frag;
+}
+
+/**
+ * Sends a newtmgr response, fragmenting it as needed. The supplied response
+ * mbuf is consumed on success and in some failure cases. If the mbuf is
+ * consumed, the supplied pointer is set to NULL.
+ *
+ * This function prefers not to consume the supplied mbuf on failure. The
+ * reason for this is to allow the caller to reuse the mbuf for an error
+ * response.
+ */
+static int
+mynewt_nmgr_rsp_tx(struct mynewt_nmgr_transport *mnt, struct os_mbuf **rsp,
+ uint16_t mtu)
+{
+ struct os_mbuf *frag;
+ int rc;
+
+ while (*rsp != NULL) {
+ frag = mem_split_frag(rsp, mtu, nmgr_rsp_frag_alloc, *rsp);
+ if (frag == NULL) {
+ return MGMT_ERR_ENOMEM;
+ }
+
+ rc = mnt->mnt_xport.nt_output(&mnt->mnt_xport, frag);
+ if (rc != 0) {
+ /* Output function already freed mbuf. */
+ return MGMT_ERR_EUNKNOWN;
+ }
+ }
+
+ return MGMT_ERR_EOK;
+}
+
+static int
+mynewt_nmgr_process_single_packet(struct mynewt_nmgr_transport *mnt,
+ struct os_mbuf *req)
+{
+ struct nmgr_hdr req_hdr;
+ struct os_mbuf *rsp;
+ int err_rc;
+ int rc;
+
+ cbor_mbuf_reader_init(mynewt_nmgr_cbor_cfg.reader, req, 0);
+
+ while (1) {
+ rc = nmgr_read_hdr(&mynewt_nmgr_cbor_cfg, &req_hdr);
+ if (rc != 0) {
+ rc = 0;
+ goto done;
+ }
+
+ rsp = os_msys_get_pkthdr(512, OS_MBUF_USRHDR_LEN(req));
+ if (rsp == NULL) {
+ rc = MGMT_ERR_ENOMEM;
+ goto done;
+ }
+
+ cbor_mbuf_writer_init(mynewt_nmgr_cbor_cfg.writer, rsp);
+
+ rc = nmgr_handle_single_req(&mynewt_nmgr_cbor_cfg, &req_hdr)
+ if (rc != 0) {
+ goto done;
+ }
+
+ os_mbuf_adj(req, sizeof *req_hdr + OS_ALIGN(req_hdr.nh_len, 4));
+
+ if (OS_MBUF_PKTLEN(rsp) > 0) {
+ rc = mynewt_nmgr_rsp_tx(mnt, &rsp, 65535 /* XXX */);
+ if (rc != 0) {
+ goto done;
+ }
+ }
+ }
+
+ rc = 0;
+
+done:
+ if (rc != 0) {
+ if (rsp == NULL) {
+ rsp = req;
+ req = NULL;
+ }
+
+ os_mbuf_adj(rsp, OS_MBUF_PKTLEN(rsp));
+ cbor_mbuf_writer_init(mynewt_nmgr_cbor_cfg.writer, rsp);
+
+ err_rc = nmgr_build_err_rsp(&mynewt_nmgr_cbor_cfg, &req_hdr, rc);
+ if (err_rc == 0) {
+ err_rc = mynewt_nmgr_rsp_tx(mnt, &rsp, 65535 /* XXX */);
+ rsp = NULL;
+ }
+ }
+
+ os_mbuf_free_chain(req);
+ os_mbuf_free_chain(rsp);
+
+ return rc;
+}
+
+static void
+mynewt_nmgr_process(struct mynewt_nmgr_transport *mnt)
+{
+ struct cbor_mbuf_reader reader;
+ struct cbor_mbuf_writer writer;
+ struct os_mbuf *rsp;
+ struct os_mbuf *req;
+ int rc;
+
+ mynewt_nmgr_cbor_cfg.reader = &reader;
+ mynewt_nmgr_cbor_cfg.writer = &writer;
+
+ while (1) {
+ req = os_mqueue_get(&mnt->mnt_imq);
+ if (req == NULL) {
+ break;
+ }
+
+ rc = mynewt_nmgr_process_single_packet(mnt, req)
+ if (rc != 0) {
+ break;
+ }
+ }
+}
+
+static void
+mynewt_nmgr_event_data_in(struct os_event *ev)
+{
+ mynewt_nmgr_process(ev->ev_arg);
+}
+
+int
+mynewt_nmgr_transport_init(struct mynewt_nmgr_transport *mnt,
+ nmgr_transport_out_func_t output_func)
+{
+ int rc;
+
+ mnt->mnt_xport.nt_output = output_func;
+
+ rc = os_mqueue_init(&mnt->nt_imq, mynewt_nmgr_event_data_in, mnt);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/mgmt/newtmgr/src/newtmgr.c b/mgmt/newtmgr/src/newtmgr.c
new file mode 100644
index 0000000..cdd1c22
--- /dev/null
+++ b/mgmt/newtmgr/src/newtmgr.c
@@ -0,0 +1,205 @@
+/*
+ * 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 "syscfg/syscfg.h"
+#include "sysinit/sysinit.h"
+#include "os/os.h"
+#include "os/endian.h" /* XXX */
+
+#include "mgmt/mgmt.h"
+
+#include "newtmgr/newtmgr.h"
+
+#include "tinycbor/cbor.h"
+#include "tinycbor/cbor_mbuf_writer.h"
+#include "tinycbor/cbor_mbuf_reader.h"
+
+static uint8_t
+nmgr_rsp_op(uint8_t req_op)
+{
+ if (req_op == NMGR_OP_READ) {
+ return NMGR_OP_READ_RSP;
+ } else {
+ return NMGR_OP_WRITE_RSP;
+ }
+}
+
+static void
+nmgr_ntoh_hdr(struct nmgr_hdr *hdr)
+{
+ hdr.nh_len = ntohs(hdr.nh_len);
+ hdr.nh_group = ntohs(hdr.nh_group);
+}
+
+static void
+nmgr_hton_hdr(struct nmgr_hdr *hdr)
+{
+ hdr.nh_len = htons(hdr.nh_len);
+ hdr.nh_group = htons(hdr.nh_group);
+}
+
+static void
+nmgr_init_rsp_hdr(const struct nmgr_hdr *req_hdr, struct nmgr_hdr *rsp_hdr)
+{
+ rsp_hdr->nh_len = 0;
+ rsp_hdr->nh_flags = 0;
+ rsp_hdr->nh_op = nmgr_rsp_op(req_hdr->nh_op);
+ rsp_hdr->nh_group = req_hdr->nh_group;
+ rsp_hdr->nh_seq = req_hdr->nh_seq;
+ rsp_hdr->nh_id = req_hdr->nh_id;
+}
+
+static int
+nmgr_read_hdr(struct mgmt_cbor_cfg *cfg, struct nmgr_hdr *hdr)
+{
+ if (cfg->reader->message_size < sizeof *hdr) {
+ return MGMT_ERR_EINVAL;
+ }
+
+ cfg->reader->cpy(cfg->reader, (char *)hdr, 0, sizeof *hdr);
+ return 0;
+}
+
+static int
+nmgr_write_hdr(struct mgmt_cbor_cfg *cfg, const struct nmgr_hdr *hdr)
+{
+ rc = cfg->write_at(cfg->writer, 0, hdr, sizeof *hdr);
+ return mgmt_err_from_cbor(rc);
+}
+
+int
+nmgr_build_err_rsp(struct mgmt_cbor_cfg *cfg, const struct nmgr_hdr *req_hdr,
+ int status)
+{
+ struct CborEncoder map;
+ struct mgmt_cbuf cbuf;
+ struct nmgr_hdr rsp_hdr;
+ int rc;
+
+ rc = mgmt_cbuf_init(&cbuf, cfg);
+ if (rc != 0) {
+ return rc;
+ }
+
+ nmgr_init_rsp_hdr(req_hdr, &rsp_hdr);
+ rc = nmgr_write_hdr(cfg, &rsp_hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = cbor_encoder_create_map(encoder, &map, CborIndefiniteLength);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = mgmt_cbuf_setoerr(encoder, status);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = cbor_encoder_close_container(encoder, &map);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rsp_hdr.nh_len = htons(cbor_encode_bytes_written(encoder));
+ rc = nmgr_write_hdr(cfg, &rsp_hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+nmgr_handle_single_req(struct mgmt_cbor_cfg *cfg,
+ const struct nmgr_hdr *req_hdr)
+{
+ struct CborEncoder payload_encoder;
+ struct mgmt_cbuf cbuf;
+ struct nmgr_hdr rsp_hdr;
+ int rc;
+
+ rc = mgmt_cbuf_init(&cbuf, cfg);
+ if (rc != 0) {
+ return rc;
+ }
+
+ handler = mgmt_find_handler(req_hdr->nh_group, req_hdr->nh_id);
+ if (!handler) {
+ return MGMT_ERR_ENOENT;
+ }
+
+ /* Build response header a priori, then pass to the handlers to fill out
+ * the response data and adjust length and flags.
+ */
+ nmgr_init_rsp_hdr(req_hdr, &rsp_hdr);
+ rc = nmgr_write_hdr(cfg, &rsp_hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ /* Begin response payload. Response fields are inserted into the root
+ * map as key value pairs.
+ */
+ rc = cbor_encoder_create_map(&cbuf.encoder, &payload_encoder,
+ CborIndefiniteLength);
+ rc = mgmt_err_from_cbor(rc);
+ if (rc != 0) {
+ return rc;
+ }
+
+ if (req_hdr->nh_op == NMGR_OP_READ) {
+ if (handler->mh_read) {
+ rc = handler->mh_read(&cbuf);
+ } else {
+ rc = MGMT_ERR_ENOENT;
+ }
+ } else if (req_hdr->nh_op == NMGR_OP_WRITE) {
+ if (handler->mh_write) {
+ rc = handler->mh_write(&cbuf);
+ } else {
+ rc = MGMT_ERR_ENOENT;
+ }
+ } else {
+ rc = MGMT_ERR_EINVAL;
+ }
+ if (rc != 0) {
+ return rc;
+ }
+
+ /* End response payload. */
+ rc = cbor_encoder_close_container(&cbuf.encoder, &payload_encoder);
+ rc = mgmt_err_from_cbor(rc);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rsp_hdr.nh_len = cbor_encode_bytes_written(&cbuf.encoder);
+ nmgr_hton_hdr(&rsp_hdr);
+ rc = nmgr_write_hdr(cfg, &rsp_hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/mgmt/newtmgr/transport/ble/include/nmgrble/newtmgr_ble.h b/mgmt/newtmgr/transport/ble/include/nmgrble/newtmgr_ble.h
new file mode 100644
index 0000000..4666d04
--- /dev/null
+++ b/mgmt/newtmgr/transport/ble/include/nmgrble/newtmgr_ble.h
@@ -0,0 +1,42 @@
+/*
+ * 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 _NEWTMGR_BLE_H_
+#define _NEWTMGR_BLE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nmgr_hdr;
+
+int
+nmgr_ble_proc_mq_evt(struct os_event *ev);
+
+int
+nmgr_ble_gatt_svr_init(void);
+
+void
+nmgr_ble_update_rsp_len(struct os_mbuf *req, uint16_t *len, uint8_t *flags);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NETMGR_H */
diff --git a/mgmt/newtmgr/transport/ble/pkg.yml b/mgmt/newtmgr/transport/ble/pkg.yml
new file mode 100644
index 0000000..af3dc32
--- /dev/null
+++ b/mgmt/newtmgr/transport/ble/pkg.yml
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+pkg.name: mgmt/newtmgr/transport/ble
+pkg.description: BLE transport newtmgr functionality.
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - ble
+ - bluetooth
+
+pkg.deps:
+ - kernel/os
+ - mgmt/mgmt
+ - mgmt/newtmgr
+ - net/nimble/host
+
+pkg.init:
+ newtmgr_ble_pkg_init: 501
diff --git a/mgmt/newtmgr/transport/ble/src/newtmgr_ble.c b/mgmt/newtmgr/transport/ble/src/newtmgr_ble.c
new file mode 100644
index 0000000..907e1c7
--- /dev/null
+++ b/mgmt/newtmgr/transport/ble/src/newtmgr_ble.c
@@ -0,0 +1,242 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include "sysinit/sysinit.h"
+#include "host/ble_hs.h"
+#include "mgmt/mgmt.h"
+#include "newtmgr/newtmgr.h"
+#include "os/endian.h"
+#include "console/console.h"
+
+/* nmgr ble mqueue */
+struct os_mqueue nmgr_ble_mq;
+
+/* ble nmgr transport */
+struct nmgr_transport ble_nt;
+
+/* ble nmgr attr handle */
+uint16_t g_ble_nmgr_attr_handle;
+
+/**
+ * The vendor specific "newtmgr" service consists of one write no-rsp
+ * characteristic for newtmgr requests: a single-byte characteristic that can
+ * only accepts write-without-response commands. The contents of each write
+ * command contains an NMP request. NMP responses are sent back in the form of
+ * unsolicited notifications from the same characteristic.
+ */
+
+/* {8D53DC1D-1DB7-4CD3-868B-8A527460AA84} */
+static const ble_uuid128_t gatt_svr_svc_newtmgr =
+ BLE_UUID128_INIT(0x84, 0xaa, 0x60, 0x74, 0x52, 0x8a, 0x8b, 0x86,
+ 0xd3, 0x4c, 0xb7, 0x1d, 0x1d, 0xdc, 0x53, 0x8d);
+
+/* {DA2E7828-FBCE-4E01-AE9E-261174997C48} */
+static const ble_uuid128_t gatt_svr_chr_newtmgr =
+ BLE_UUID128_INIT(0x48, 0x7c, 0x99, 0x74, 0x11, 0x26, 0x9e, 0xae,
+ 0x01, 0x4e, 0xce, 0xfb, 0x28, 0x78, 0x2e, 0xda);
+
+static int
+gatt_svr_chr_access_newtmgr(uint16_t conn_handle, uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt, void *arg);
+
+static const struct ble_gatt_svc_def gatt_svr_svcs[] = {
+ {
+ /* Service: newtmgr */
+ .type = BLE_GATT_SVC_TYPE_PRIMARY,
+ .uuid = &gatt_svr_svc_newtmgr.u,
+ .characteristics = (struct ble_gatt_chr_def[]) { {
+ /* Characteristic: Write No Rsp */
+ .uuid = &gatt_svr_chr_newtmgr.u,
+ .access_cb = gatt_svr_chr_access_newtmgr,
+ .flags = BLE_GATT_CHR_F_WRITE_NO_RSP | BLE_GATT_CHR_F_NOTIFY,
+ .val_handle = &g_ble_nmgr_attr_handle,
+ }, {
+ 0, /* No more characteristics in this service */
+ } },
+ },
+
+ {
+ 0, /* No more services */
+ },
+};
+
+static int
+gatt_svr_chr_access_newtmgr(uint16_t conn_handle, uint16_t attr_handle,
+ struct ble_gatt_access_ctxt *ctxt, void *arg)
+{
+ int rc;
+ struct os_mbuf *m_req;
+
+ switch (ctxt->op) {
+ case BLE_GATT_ACCESS_OP_WRITE_CHR:
+ /* Try to reuse the BLE packet mbuf as the newtmgr request. This
+ * requires a two-byte usrhdr to hold the BLE connection handle so
+ * that the newtmgr response can be sent to the correct peer. If
+ * it is not possible to reuse the mbuf, then allocate a new one
+ * and copy the request contents.
+ */
+ if (OS_MBUF_USRHDR_LEN(ctxt->om) >= sizeof (conn_handle)) {
+ /* Sufficient usrhdr space already present. */
+ m_req = ctxt->om;
+ ctxt->om = NULL;
+ } else if (OS_MBUF_LEADINGSPACE(ctxt->om) >=
+ sizeof (conn_handle)) {
+
+ /* Usrhdr isn't present, but there is enough leading space to
+ * add one.
+ */
+ m_req = ctxt->om;
+ ctxt->om = NULL;
+
+ m_req->om_pkthdr_len += sizeof (conn_handle);
+ } else {
+ /* The mbuf can't be reused. Allocate a new one and perform a
+ * copy. Don't set ctxt->om to NULL; let the NimBLE host free
+ * it.
+ */
+ m_req = os_msys_get_pkthdr(OS_MBUF_PKTLEN(ctxt->om),
+ sizeof (conn_handle));
+ if (!m_req) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+ rc = os_mbuf_appendfrom(m_req, ctxt->om, 0,
+ OS_MBUF_PKTLEN(ctxt->om));
+ if (rc) {
+ return BLE_ATT_ERR_INSUFFICIENT_RES;
+ }
+ }
+
+ /* Write the connection handle to the newtmgr request usrhdr. This
+ * is necessary so that we later know who to send the newtmgr
+ * response to.
+ */
+ memcpy(OS_MBUF_USRHDR(m_req), &conn_handle, sizeof(conn_handle));
+
+ rc = nmgr_rx_req(&ble_nt, m_req);
+ if (rc != 0) {
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+ return 0;
+
+ default:
+ assert(0);
+ return BLE_ATT_ERR_UNLIKELY;
+ }
+}
+
+uint16_t
+nmgr_ble_get_mtu(struct os_mbuf *req) {
+
+ uint16_t conn_handle;
+ uint16_t mtu;
+
+ memcpy(&conn_handle, OS_MBUF_USRHDR(req), sizeof (conn_handle));
+ mtu = ble_att_mtu(conn_handle);
+ if (!mtu) {
+ /* No longer connected. */
+ return 0;
+ }
+
+ /* 3 is the number of bytes for ATT notification base */
+ mtu = mtu - 3;
+
+ return (mtu);
+}
+
+/**
+ * Nmgr ble process mqueue event
+ * Gets an event from the nmgr mqueue and does a notify with the response
+ *
+ * @param eventq
+ * @return 0 on success; non-zero on failure
+ */
+
+static void
+nmgr_ble_event_data_in(struct os_event *ev)
+{
+ struct os_mbuf *m_resp;
+ uint16_t conn_handle;
+
+ while ((m_resp = os_mqueue_get(&nmgr_ble_mq)) != NULL) {
+ assert(OS_MBUF_USRHDR_LEN(m_resp) >= sizeof (conn_handle));
+ memcpy(&conn_handle, OS_MBUF_USRHDR(m_resp), sizeof (conn_handle));
+ ble_gattc_notify_custom(conn_handle, g_ble_nmgr_attr_handle,
+ m_resp);
+ }
+}
+
+static int
+nmgr_ble_out(struct nmgr_transport *nt, struct os_mbuf *om)
+{
+ int rc;
+
+ rc = os_mqueue_put(&nmgr_ble_mq, mgmt_evq_get(), om);
+ if (rc != 0) {
+ goto err;
+ }
+
+ return (0);
+err:
+ os_mbuf_free_chain(om);
+ return (rc);
+}
+
+/**
+ * Nmgr ble GATT server initialization
+ *
+ * @param eventq
+ * @return 0 on success; non-zero on failure
+ */
+int
+nmgr_ble_gatt_svr_init(void)
+{
+ int rc;
+
+ rc = ble_gatts_count_cfg(gatt_svr_svcs);
+ if (rc != 0) {
+ goto err;
+ }
+
+ rc = ble_gatts_add_svcs(gatt_svr_svcs);
+ if (rc != 0) {
+ return rc;
+ }
+
+ os_mqueue_init(&nmgr_ble_mq, &nmgr_ble_event_data_in, NULL);
+
+ rc = nmgr_transport_init(&ble_nt, nmgr_ble_out, nmgr_ble_get_mtu);
+
+err:
+ return rc;
+}
+
+void
+newtmgr_ble_pkg_init(void)
+{
+ int rc;
+
+ /* Ensure this function only gets called by sysinit. */
+ SYSINIT_ASSERT_ACTIVE();
+
+ rc = nmgr_ble_gatt_svr_init();
+ SYSINIT_PANIC_ASSERT(rc == 0);
+}
diff --git a/mgmt/newtmgr/transport/nmgr_shell/pkg.yml b/mgmt/newtmgr/transport/nmgr_shell/pkg.yml
new file mode 100644
index 0000000..2a859cb
--- /dev/null
+++ b/mgmt/newtmgr/transport/nmgr_shell/pkg.yml
@@ -0,0 +1,34 @@
+#
+# 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.
+#
+
+pkg.name: mgmt/newtmgr/transport/nmgr_shell
+pkg.description: Newtmgr transport over shell
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - newtmgr
+ - shell
+
+pkg.deps:
+ - kernel/os
+ - sys/shell
+ - mgmt/newtmgr
+
+pkg.init:
+ nmgr_shell_pkg_init: 501
diff --git a/mgmt/newtmgr/transport/nmgr_shell/src/nmgr_shell.c b/mgmt/newtmgr/transport/nmgr_shell/src/nmgr_shell.c
new file mode 100644
index 0000000..c57e9b1
--- /dev/null
+++ b/mgmt/newtmgr/transport/nmgr_shell/src/nmgr_shell.c
@@ -0,0 +1,71 @@
+/*
+ * 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 <inttypes.h>
+#include <assert.h>
+
+#include <sysinit/sysinit.h>
+#include <shell/shell.h>
+#include <mgmt/mgmt.h>
+#include <newtmgr/newtmgr.h>
+
+static struct nmgr_transport nmgr_shell_transport;
+
+static uint16_t
+nmgr_shell_get_mtu(struct os_mbuf *m)
+{
+ return MGMT_MAX_MTU;
+}
+
+static int
+nmgr_shell_out(struct nmgr_transport *nt, struct os_mbuf *m)
+{
+ int rc;
+
+ rc = shell_nlip_output(m);
+ if (rc != 0) {
+ goto err;
+ }
+
+ return (0);
+err:
+ os_mbuf_free_chain(m);
+ return (rc);
+}
+
+static int
+nmgr_shell_in(struct os_mbuf *m, void *arg)
+{
+ return nmgr_rx_req(&nmgr_shell_transport, m);
+}
+
+void
+nmgr_shell_pkg_init(void)
+{
+ int rc;
+
+ /* Ensure this function only gets called by sysinit. */
+ SYSINIT_ASSERT_ACTIVE();
+
+ rc = nmgr_transport_init(&nmgr_shell_transport, nmgr_shell_out,
+ nmgr_shell_get_mtu);
+ assert(rc == 0);
+
+ rc = shell_nlip_input_register(nmgr_shell_in, &nmgr_shell_transport);
+ assert(rc == 0);
+}
diff --git a/mgmt/newtmgr/transport/nmgr_uart/pkg.yml b/mgmt/newtmgr/transport/nmgr_uart/pkg.yml
new file mode 100644
index 0000000..9e62a32
--- /dev/null
+++ b/mgmt/newtmgr/transport/nmgr_uart/pkg.yml
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+pkg.name: mgmt/newtmgr/transport/nmgr_uart
+pkg.description: Newtmgr transport over raw UART
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - newtmgr
+ - uart
+
+pkg.deps:
+ - kernel/os
+ - hw/drivers/uart
+ - mgmt/newtmgr
+ - util/crc
+
+pkg.init:
+ nmgr_uart_pkg_init: 501
diff --git a/mgmt/newtmgr/transport/nmgr_uart/src/nmgr_uart.c b/mgmt/newtmgr/transport/nmgr_uart/src/nmgr_uart.c
new file mode 100644
index 0000000..4465079
--- /dev/null
+++ b/mgmt/newtmgr/transport/nmgr_uart/src/nmgr_uart.c
@@ -0,0 +1,389 @@
+/*
+ * 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 <inttypes.h>
+#include <assert.h>
+
+#include <syscfg/syscfg.h>
+#include <sysinit/sysinit.h>
+#include <bsp/bsp.h>
+
+#include <os/os.h>
+#include <mgmt/mgmt.h>
+#include <newtmgr/newtmgr.h>
+#include <uart/uart.h>
+
+#include <crc/crc16.h>
+#include <base64/base64.h>
+
+#define SHELL_NLIP_PKT 0x0609
+#define SHELL_NLIP_DATA 0x0414
+#define SHELL_NLIP_MAX_FRAME 128
+
+#define NUS_EV_TO_STATE(ptr) \
+ (struct nmgr_uart_state *)((uint8_t *)ptr - \
+ (int)&(((struct nmgr_uart_state *)0)->nus_cb_ev))
+
+struct nmgr_uart_state {
+ struct nmgr_transport nus_transport; /* keep first in struct */
+ struct os_event nus_cb_ev;
+ struct uart_dev *nus_dev;
+ struct os_mbuf *nus_tx;
+ int nus_tx_off;
+ struct os_mbuf_pkthdr *nus_rx_pkt;
+ struct os_mbuf_pkthdr *nus_rx_q;
+ struct os_mbuf_pkthdr *nus_rx;
+};
+
+/*
+ * Header for frames arriving over serial.
+ */
+struct nmgr_ser_hdr {
+ uint16_t nsh_seq;
+ uint16_t nsh_len;
+};
+
+static struct nmgr_uart_state nmgr_uart_state;
+
+static uint16_t
+nmgr_uart_mtu(struct os_mbuf *m)
+{
+ return MGMT_MAX_MTU;
+}
+
+/*
+ * Called by mgmt to queue packet out to UART.
+ */
+static int
+nmgr_uart_out(struct nmgr_transport *nt, struct os_mbuf *m)
+{
+ struct nmgr_uart_state *nus = (struct nmgr_uart_state *)nt;
+ struct os_mbuf_pkthdr *mpkt;
+ struct os_mbuf *n;
+ uint16_t tmp_buf[6];
+ char *dst;
+ int off;
+ int boff;
+ int slen;
+ int sr;
+ int rc;
+ int last;
+ int tx_sz;
+
+ assert(OS_MBUF_IS_PKTHDR(m));
+ mpkt = OS_MBUF_PKTHDR(m);
+
+ /*
+ * Compute CRC-16 and append it to end.
+ */
+ off = 0;
+ tmp_buf[0] = CRC16_INITIAL_CRC;
+ for (n = m; n; n = SLIST_NEXT(n, om_next)) {
+ tmp_buf[0] = crc16_ccitt(tmp_buf[0], n->om_data, n->om_len);
+ }
+ tmp_buf[0] = htons(tmp_buf[0]);
+ dst = os_mbuf_extend(m, sizeof(uint16_t));
+ if (!dst) {
+ goto err;
+ }
+ memcpy(dst, tmp_buf, sizeof(uint16_t));
+
+ /*
+ * Create another mbuf chain with base64 encoded data.
+ */
+ n = os_msys_get(SHELL_NLIP_MAX_FRAME, 0);
+ if (!n || OS_MBUF_TRAILINGSPACE(n) < 32) {
+ goto err;
+ }
+
+ while (off < mpkt->omp_len) {
+ /*
+ * First fragment has a different header, and length of the full frame
+ * (need to base64 encode that).
+ */
+ if (off == 0) {
+ tmp_buf[0] = htons(SHELL_NLIP_PKT);
+ } else {
+ tmp_buf[0] = htons(SHELL_NLIP_DATA);
+ }
+ rc = os_mbuf_append(n, tmp_buf, sizeof(uint16_t));
+ if (rc) {
+ goto err;
+ }
+ tx_sz = 2;
+
+ if (off == 0) {
+ tmp_buf[0] = htons(mpkt->omp_len);
+ boff = sizeof(uint16_t);
+ } else {
+ boff = 0;
+ }
+
+ while (off < mpkt->omp_len) {
+ slen = mpkt->omp_len - off;
+ last = 1;
+ if (slen > sizeof(tmp_buf) + boff) {
+ slen = sizeof(tmp_buf) - boff;
+ last = 0;
+ }
+ if (tx_sz + BASE64_ENCODE_SIZE(slen + boff) >= 124) {
+ break;
+ }
+ rc = os_mbuf_copydata(m, off, slen, (uint8_t *)tmp_buf + boff);
+ assert(rc == 0);
+
+ off += slen;
+ slen += boff;
+
+ dst = os_mbuf_extend(n, BASE64_ENCODE_SIZE(slen));
+ if (!dst) {
+ goto err;
+ }
+ tx_sz += base64_encode(tmp_buf, slen, dst, last);
+ boff = 0;
+ }
+
+ if (os_mbuf_append(n, "\n", 1)) {
+ goto err;
+ }
+ }
+
+ os_mbuf_free_chain(m);
+ OS_ENTER_CRITICAL(sr);
+ if (!nus->nus_tx) {
+ nus->nus_tx = n;
+ uart_start_tx(nus->nus_dev);
+ } else {
+ os_mbuf_concat(nus->nus_tx, n);
+ }
+ OS_EXIT_CRITICAL(sr);
+
+ return 0;
+err:
+ os_mbuf_free_chain(m);
+ os_mbuf_free_chain(n);
+ return -1;
+}
+
+/*
+ * Called by UART driver to send out next character.
+ *
+ * Interrupts disabled when nmgr_uart_tx_char/nmgr_uart_rx_char are called.
+ */
+static int
+nmgr_uart_tx_char(void *arg)
+{
+ struct nmgr_uart_state *nus = (struct nmgr_uart_state *)arg;
+ struct os_mbuf *m;
+ uint8_t ch;
+
+ if (!nus->nus_tx) {
+ /*
+ * Out of data. Return -1 makes UART stop asking for more.
+ */
+ return -1;
+ }
+ while (nus->nus_tx->om_len == nus->nus_tx_off) {
+ /*
+ * If no active mbuf, move to next one.
+ */
+ m = SLIST_NEXT(nus->nus_tx, om_next);
+ os_mbuf_free(nus->nus_tx);
+ nus->nus_tx = m;
+
+ nus->nus_tx_off = 0;
+ if (!nus->nus_tx) {
+ return -1;
+ }
+ }
+
+ os_mbuf_copydata(nus->nus_tx, nus->nus_tx_off++, 1, &ch);
+
+ return ch;
+}
+
+/*
+ * Check for full packet. If frame is not right, free the mbuf.
+ */
+static void
+nmgr_uart_rx_pkt(struct nmgr_uart_state *nus, struct os_mbuf_pkthdr *rxm)
+{
+ struct os_mbuf *m;
+ struct nmgr_ser_hdr *nsh;
+ uint16_t crc;
+ int rc;
+
+ m = OS_MBUF_PKTHDR_TO_MBUF(rxm);
+
+ if (rxm->omp_len <= sizeof(uint16_t) + sizeof(crc)) {
+ goto err;
+ }
+
+ nsh = (struct nmgr_ser_hdr *)m->om_data;
+ switch (nsh->nsh_seq) {
+ case htons(SHELL_NLIP_PKT):
+ if (nus->nus_rx_pkt) {
+ os_mbuf_free_chain(OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx_pkt));
+ nus->nus_rx_pkt = NULL;
+ }
+ break;
+ case htons(SHELL_NLIP_DATA):
+ if (!nus->nus_rx_pkt) {
+ goto err;
+ }
+ break;
+ default:
+ goto err;
+ }
+
+ if (os_mbuf_append(m, "\0", 1)) {
+ /*
+ * Null-terminate the line for base64_decode's sake.
+ */
+ goto err;
+ }
+ m = os_mbuf_pullup(m, rxm->omp_len);
+ if (!m) {
+ /*
+ * Make data contiguous for base64_decode's sake.
+ */
+ goto err;
+ }
+ rxm = OS_MBUF_PKTHDR(m);
+ rc = base64_decode((char *)m->om_data + 2, (char *)m->om_data + 2);
+ if (rc < 0) {
+ goto err;
+ }
+ rxm->omp_len = m->om_len = rc + 2;
+ if (nus->nus_rx_pkt) {
+ os_mbuf_adj(m, 2);
+ os_mbuf_concat(OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx_pkt), m);
+ } else {
+ nus->nus_rx_pkt = rxm;
+ }
+
+ m = OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx_pkt);
+ nsh = (struct nmgr_ser_hdr *)m->om_data;
+ if (nus->nus_rx_pkt->omp_len - sizeof(*nsh) == ntohs(nsh->nsh_len)) {
+ os_mbuf_adj(m, 4);
+ os_mbuf_adj(m, -2);
+ nmgr_rx_req(&nus->nus_transport, m);
+ nus->nus_rx_pkt = NULL;
+ }
+ return;
+err:
+ os_mbuf_free_chain(m);
+}
+
+/*
+ * Callback from mgmt task context.
+ */
+static void
+nmgr_uart_rx_frame(struct os_event *ev)
+{
+ struct nmgr_uart_state *nus = NUS_EV_TO_STATE(ev);
+ struct os_mbuf_pkthdr *m;
+ int sr;
+
+ OS_ENTER_CRITICAL(sr);
+ m = nus->nus_rx_q;
+ nus->nus_rx_q = NULL;
+ OS_EXIT_CRITICAL(sr);
+ if (m) {
+ nmgr_uart_rx_pkt(nus, m);
+ }
+}
+
+/*
+ * Receive a character from UART.
+ */
+static int
+nmgr_uart_rx_char(void *arg, uint8_t data)
+{
+ struct nmgr_uart_state *nus = (struct nmgr_uart_state *)arg;
+ struct os_mbuf *m;
+ int rc;
+
+ if (!nus->nus_rx) {
+ m = os_msys_get_pkthdr(SHELL_NLIP_MAX_FRAME, 0);
+ if (!m) {
+ return 0;
+ }
+ nus->nus_rx = OS_MBUF_PKTHDR(m);
+ if (OS_MBUF_TRAILINGSPACE(m) < SHELL_NLIP_MAX_FRAME) {
+ /*
+ * mbuf is too small.
+ */
+ os_mbuf_free_chain(m);
+ nus->nus_rx = NULL;
+ return 0;
+ }
+ }
+
+ m = OS_MBUF_PKTHDR_TO_MBUF(nus->nus_rx);
+ if (data == '\n') {
+ /*
+ * Full line of input. Process it outside interrupt context.
+ */
+ assert(!nus->nus_rx_q);
+ nus->nus_rx_q = nus->nus_rx;
+ nus->nus_rx = NULL;
+ os_eventq_put(mgmt_evq_get(), &nus->nus_cb_ev);
+ return 0;
+ } else {
+ rc = os_mbuf_append(m, &data, 1);
+ if (rc == 0) {
+ return 0;
+ }
+ }
+ /* failed */
+ nus->nus_rx->omp_len = 0;
+ m->om_len = 0;
+ os_mbuf_free_chain(SLIST_NEXT(m, om_next));
+ SLIST_NEXT(m, om_next) = NULL;
+ return 0;
+}
+
+void
+nmgr_uart_pkg_init(void)
+{
+ struct nmgr_uart_state *nus = &nmgr_uart_state;
+ int rc;
+ struct uart_conf uc = {
+ .uc_speed = MYNEWT_VAL(NMGR_UART_SPEED),
+ .uc_databits = 8,
+ .uc_stopbits = 1,
+ .uc_parity = UART_PARITY_NONE,
+ .uc_flow_ctl = UART_FLOW_CTL_NONE,
+ .uc_tx_char = nmgr_uart_tx_char,
+ .uc_rx_char = nmgr_uart_rx_char,
+ .uc_cb_arg = nus
+ };
+
+ /* Ensure this function only gets called by sysinit. */
+ SYSINIT_ASSERT_ACTIVE();
+
+ rc = nmgr_transport_init(&nus->nus_transport, nmgr_uart_out, nmgr_uart_mtu);
+ assert(rc == 0);
+
+ nus->nus_dev =
+ (struct uart_dev *)os_dev_open(MYNEWT_VAL(NMGR_UART), 0, &uc);
+ assert(nus->nus_dev);
+
+ nus->nus_cb_ev.ev_cb = nmgr_uart_rx_frame;
+}
diff --git a/mgmt/newtmgr/transport/nmgr_uart/syscfg.yml b/mgmt/newtmgr/transport/nmgr_uart/syscfg.yml
new file mode 100644
index 0000000..2d9d15e
--- /dev/null
+++ b/mgmt/newtmgr/transport/nmgr_uart/syscfg.yml
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+syscfg.defs:
+ NMGR_UART:
+ description: 'UART port number to use for newtmgr'
+ value: '"uart0"'
+
+ NMGR_UART_SPEED:
+ description: 'Baudrate for newtmgr UART'
+ value: 115200
+
--
To stop receiving notification emails like this one, please contact
"commits@mynewt.apache.org" <co...@mynewt.apache.org>.