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:05 UTC

[mynewt-mcumgr] branch master created (now 292ca05)

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

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


      at 292ca05  Initial commit.

This branch includes the following new commits:

     new 63166fd  initial commit
     new 292ca05  Initial commit.

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
['"commits@mynewt.apache.org" <co...@mynewt.apache.org>'].

[mynewt-mcumgr] 01/02: initial commit

Posted by cc...@apache.org.
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>.

[mynewt-mcumgr] 02/02: Initial commit.

Posted by cc...@apache.org.
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 292ca05d9bbfb7842bcab25a55b7a88df6ca3889
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Thu Dec 7 16:55:48 2017 -0800

    Initial commit.
---
 README.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..3a9710e
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# mynewt-mcumgr

-- 
To stop receiving notification emails like this one, please contact
"commits@mynewt.apache.org" <co...@mynewt.apache.org>.