Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop cf8600229 -> b99324aa6


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/newtmgr/nmgr_os/src/newtmgr_os.c
----------------------------------------------------------------------
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..6c1a12f
--- /dev/null
+++ b/mgmt/newtmgr/nmgr_os/src/newtmgr_os.c
@@ -0,0 +1,326 @@
+/**
+ * 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 <os/os.h>
+#include <os/endian.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <hal/hal_system.h>
+
+#include <newtmgr/newtmgr.h>
+
+#include <console/console.h>
+#include <util/datetime.h>
+#include <reboot/log_reboot.h>
+
+#include "nmgr_os/nmgr_os.h"
+
+static struct os_callout_func nmgr_reset_callout;
+
+static int nmgr_def_echo(struct nmgr_jbuf *);
+static int nmgr_def_console_echo(struct nmgr_jbuf *);
+static int nmgr_def_taskstat_read(struct nmgr_jbuf *njb);
+static int nmgr_def_mpstat_read(struct nmgr_jbuf *njb);
+static int nmgr_datetime_get(struct nmgr_jbuf *njb);
+static int nmgr_datetime_set(struct nmgr_jbuf *njb);
+static int nmgr_reset(struct nmgr_jbuf *njb);
+
+static const struct nmgr_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 nmgr_group nmgr_def_group = {
+    .ng_handlers = (struct nmgr_handler *)nmgr_def_group_handlers,
+    .ng_handlers_count = NMGR_DEF_GROUP_SZ,
+    .ng_group_id = NMGR_GROUP_ID_DEFAULT
+};
+
+static int
+nmgr_def_echo(struct nmgr_jbuf *njb)
+{
+    uint8_t echo_buf[128];
+    struct json_attr_t attrs[] = {
+        { "d", t_string, .addr.string = (char *) &echo_buf[0],
+            .len = sizeof(echo_buf) },
+        { NULL },
+    };
+    struct json_value jv;
+    int rc;
+
+    rc = json_read_object((struct json_buffer *) njb, attrs);
+    if (rc != 0) {
+        goto err;
+    }
+
+    json_encode_object_start(&njb->njb_enc);
+    JSON_VALUE_STRINGN(&jv, (char *) echo_buf, strlen((char *) echo_buf));
+    json_encode_object_entry(&njb->njb_enc, "r", &jv);
+    json_encode_object_finish(&njb->njb_enc);
+
+    return (0);
+err:
+    return (rc);
+}
+
+static int
+nmgr_def_console_echo(struct nmgr_jbuf *njb)
+{
+    long long int echo_on = 1;
+    int rc;
+    struct json_attr_t attrs[3] = {
+        [0] = {
+            .attribute = "echo",
+            .type = t_integer,
+            .addr.integer = &echo_on,
+            .nodefault = 1
+        },
+        [1] = {
+            .attribute = NULL
+        }
+    };
+
+    rc = json_read_object(&njb->njb_buf, attrs);
+    if (rc) {
+        return OS_EINVAL;
+    }
+
+    if (echo_on) {
+        console_echo(1);
+    } else {
+        console_echo(0);
+    }
+    return (0);
+}
+
+static int
+nmgr_def_taskstat_read(struct nmgr_jbuf *njb)
+{
+    struct os_task *prev_task;
+    struct os_task_info oti;
+    struct json_value jv;
+
+    json_encode_object_start(&njb->njb_enc);
+    JSON_VALUE_INT(&jv, NMGR_ERR_EOK);
+    json_encode_object_entry(&njb->njb_enc, "rc", &jv);
+
+    json_encode_object_key(&njb->njb_enc, "tasks");
+    json_encode_object_start(&njb->njb_enc);
+
+    prev_task = NULL;
+    while (1) {
+        prev_task = os_task_info_get_next(prev_task, &oti);
+        if (prev_task == NULL) {
+            break;
+        }
+
+        json_encode_object_key(&njb->njb_enc, oti.oti_name);
+
+        json_encode_object_start(&njb->njb_enc);
+        JSON_VALUE_UINT(&jv, oti.oti_prio);
+        json_encode_object_entry(&njb->njb_enc, "prio", &jv);
+        JSON_VALUE_UINT(&jv, oti.oti_taskid);
+        json_encode_object_entry(&njb->njb_enc, "tid", &jv);
+        JSON_VALUE_UINT(&jv, oti.oti_state);
+        json_encode_object_entry(&njb->njb_enc, "state", &jv);
+        JSON_VALUE_UINT(&jv, oti.oti_stkusage);
+        json_encode_object_entry(&njb->njb_enc, "stkuse", &jv);
+        JSON_VALUE_UINT(&jv, oti.oti_stksize);
+        json_encode_object_entry(&njb->njb_enc, "stksiz", &jv);
+        JSON_VALUE_UINT(&jv, oti.oti_cswcnt);
+        json_encode_object_entry(&njb->njb_enc, "cswcnt", &jv);
+        JSON_VALUE_UINT(&jv, oti.oti_runtime);
+        json_encode_object_entry(&njb->njb_enc, "runtime", &jv);
+        JSON_VALUE_UINT(&jv, oti.oti_last_checkin);
+        json_encode_object_entry(&njb->njb_enc, "last_checkin", &jv);
+        JSON_VALUE_UINT(&jv, oti.oti_next_checkin);
+        json_encode_object_entry(&njb->njb_enc, "next_checkin", &jv);
+        json_encode_object_finish(&njb->njb_enc);
+    }
+    json_encode_object_finish(&njb->njb_enc);
+    json_encode_object_finish(&njb->njb_enc);
+
+    return (0);
+}
+
+static int
+nmgr_def_mpstat_read(struct nmgr_jbuf *njb)
+{
+    struct os_mempool *prev_mp;
+    struct os_mempool_info omi;
+    struct json_value jv;
+
+    json_encode_object_start(&njb->njb_enc);
+    JSON_VALUE_INT(&jv, NMGR_ERR_EOK);
+    json_encode_object_entry(&njb->njb_enc, "rc", &jv);
+
+    json_encode_object_key(&njb->njb_enc, "mpools");
+    json_encode_object_start(&njb->njb_enc);
+
+    prev_mp = NULL;
+    while (1) {
+        prev_mp = os_mempool_info_get_next(prev_mp, &omi);
+        if (prev_mp == NULL) {
+            break;
+        }
+
+        json_encode_object_key(&njb->njb_enc, omi.omi_name);
+
+        json_encode_object_start(&njb->njb_enc);
+        JSON_VALUE_UINT(&jv, omi.omi_block_size);
+        json_encode_object_entry(&njb->njb_enc, "blksiz", &jv);
+        JSON_VALUE_UINT(&jv, omi.omi_num_blocks);
+        json_encode_object_entry(&njb->njb_enc, "nblks", &jv);
+        JSON_VALUE_UINT(&jv, omi.omi_num_free);
+        json_encode_object_entry(&njb->njb_enc, "nfree", &jv);
+        json_encode_object_finish(&njb->njb_enc);
+    }
+
+    json_encode_object_finish(&njb->njb_enc);
+    json_encode_object_finish(&njb->njb_enc);
+
+    return (0);
+}
+
+static int
+nmgr_datetime_get(struct nmgr_jbuf *njb)
+{
+    struct os_timeval tv;
+    struct os_timezone tz;
+    char buf[DATETIME_BUFSIZE];
+    struct json_value jv;
+    int rc;
+
+    json_encode_object_start(&njb->njb_enc);
+    JSON_VALUE_INT(&jv, NMGR_ERR_EOK);
+    json_encode_object_entry(&njb->njb_enc, "rc", &jv);
+
+    /* Display the current datetime */
+    rc = os_gettimeofday(&tv, &tz);
+    assert(rc == 0);
+    rc = format_datetime(&tv, &tz, buf, DATETIME_BUFSIZE);
+    if (rc) {
+        rc = OS_EINVAL;
+        goto err;
+    }
+
+    JSON_VALUE_STRING(&jv, buf)
+    json_encode_object_entry(&njb->njb_enc, "datetime", &jv);
+    json_encode_object_finish(&njb->njb_enc);
+
+    return OS_OK;
+err:
+    return (rc);
+}
+
+static int
+nmgr_datetime_set(struct nmgr_jbuf *njb)
+{
+    struct os_timeval tv;
+    struct os_timezone tz;
+    struct json_value jv;
+    char buf[DATETIME_BUFSIZE];
+    int rc = OS_OK;
+    const struct json_attr_t datetime_write_attr[2] = {
+        [0] = {
+            .attribute = "datetime",
+            .type = t_string,
+            .addr.string = buf,
+            .len = sizeof(buf),
+        },
+        [1] = {
+            .attribute = "rc",
+            .type = t_uinteger,
+
+        }
+    };
+
+    rc = json_read_object(&njb->njb_buf, datetime_write_attr);
+    if (rc) {
+        rc = OS_EINVAL;
+        goto out;
+    }
+
+    /* Set the current datetime */
+    rc = parse_datetime(buf, &tv, &tz);
+    if (!rc) {
+        rc = os_settimeofday(&tv, &tz);
+        if (rc) {
+          rc = OS_EINVAL;
+          goto out;
+        }
+    } else {
+        rc = OS_EINVAL;
+        goto out;
+    }
+
+out:
+    json_encode_object_start(&njb->njb_enc);
+    JSON_VALUE_INT(&jv, rc);
+    json_encode_object_entry(&njb->njb_enc, "rc", &jv);
+    json_encode_object_finish(&njb->njb_enc);
+    return OS_OK;
+}
+
+static void
+nmgr_reset_tmo(void *arg)
+{
+    system_reset();
+}
+
+static int
+nmgr_reset(struct nmgr_jbuf *njb)
+{
+    log_reboot(SOFT_REBOOT);
+    os_callout_reset(&nmgr_reset_callout.cf_c, OS_TICKS_PER_SEC / 4);
+
+    nmgr_jbuf_setoerr(njb, 0);
+
+    return OS_OK;
+}
+
+int
+nmgr_os_groups_register(struct os_eventq *nmgr_evq)
+{
+    os_callout_func_init(&nmgr_reset_callout, nmgr_evq, nmgr_reset_tmo, NULL);
+
+    return nmgr_group_register(&nmgr_def_group);
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/newtmgr/pkg.yml
----------------------------------------------------------------------
diff --git a/mgmt/newtmgr/pkg.yml b/mgmt/newtmgr/pkg.yml
new file mode 100644
index 0000000..1bde967
--- /dev/null
+++ b/mgmt/newtmgr/pkg.yml
@@ -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.
+#
+
+pkg.name: mgmt/newtmgr
+pkg.description: Server-side newtmgr functionality.
+pkg.author: "Apache Mynewt <d...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/";
+pkg.keywords:
+
+pkg.deps:
+    - hw/hal
+    - kernel/os
+    - encoding/json
+    - mgmt/newtmgr/nmgr_os
+    - libs/util
+    - sys/shell
+    - sys/reboot
+
+pkg.deps.NEWTMGR_BLE_HOST:
+    - mgmt/newtmgr/transport/ble
+
+pkg.apis:
+    - newtmgr
+
+pkg.init_function: nmgr_pkg_init
+pkg.init_stage: 5

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/newtmgr/src/newtmgr.c
----------------------------------------------------------------------
diff --git a/mgmt/newtmgr/src/newtmgr.c b/mgmt/newtmgr/src/newtmgr.c
new file mode 100644
index 0000000..9b90296
--- /dev/null
+++ b/mgmt/newtmgr/src/newtmgr.c
@@ -0,0 +1,694 @@
+/**
+ * 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"
+
+#include "shell/shell.h"
+#include "newtmgr/newtmgr.h"
+#include "nmgr_os/nmgr_os.h"
+
+os_stack_t newtmgr_stack[OS_STACK_ALIGN(MYNEWT_VAL(NEWTMGR_STACK_SIZE))];
+
+struct nmgr_transport g_nmgr_shell_transport;
+
+struct os_mutex g_nmgr_group_list_lock;
+
+static struct os_eventq g_nmgr_evq;
+static struct os_task g_nmgr_task;
+
+STAILQ_HEAD(, nmgr_group) g_nmgr_group_list =
+    STAILQ_HEAD_INITIALIZER(g_nmgr_group_list);
+
+/* JSON buffer for NMGR task
+ */
+static struct nmgr_jbuf nmgr_task_jbuf;
+
+int
+nmgr_group_list_lock(void)
+{
+    int rc;
+
+    if (!os_started()) {
+        return (0);
+    }
+
+    rc = os_mutex_pend(&g_nmgr_group_list_lock, OS_WAIT_FOREVER);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+int
+nmgr_group_list_unlock(void)
+{
+    int rc;
+
+    if (!os_started()) {
+        return (0);
+    }
+
+    rc = os_mutex_release(&g_nmgr_group_list_lock);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+int
+nmgr_group_register(struct nmgr_group *group)
+{
+    int rc;
+
+    rc = nmgr_group_list_lock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    STAILQ_INSERT_TAIL(&g_nmgr_group_list, group, ng_next);
+
+    rc = nmgr_group_list_unlock();
+    if (rc != 0) {
+        goto err;
+    }
+
+
+    return (0);
+err:
+    return (rc);
+}
+
+static struct nmgr_group *
+nmgr_find_group(uint16_t group_id)
+{
+    struct nmgr_group *group;
+    int rc;
+
+    group = NULL;
+
+    rc = nmgr_group_list_lock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    STAILQ_FOREACH(group, &g_nmgr_group_list, ng_next) {
+        if (group->ng_group_id == group_id) {
+            break;
+        }
+    }
+
+    rc = nmgr_group_list_unlock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (group);
+err:
+    return (NULL);
+}
+
+static struct nmgr_handler *
+nmgr_find_handler(uint16_t group_id, uint16_t handler_id)
+{
+    struct nmgr_group *group;
+    struct nmgr_handler *handler;
+
+    group = nmgr_find_group(group_id);
+    if (!group) {
+        goto err;
+    }
+
+    if (handler_id >= group->ng_handlers_count) {
+        goto err;
+    }
+
+    handler = &group->ng_handlers[handler_id];
+
+    return (handler);
+err:
+    return (NULL);
+}
+
+int
+nmgr_rsp_extend(struct nmgr_hdr *hdr, struct os_mbuf *rsp, void *data,
+        uint16_t len)
+{
+    int rc;
+
+    rc = os_mbuf_append(rsp, data, len);
+    if (rc != 0) {
+        goto err;
+    }
+    hdr->nh_len += len;
+
+    return (0);
+err:
+    return (rc);
+}
+
+static char
+nmgr_jbuf_read_next(struct json_buffer *jb)
+{
+    struct nmgr_jbuf *njb;
+    char c;
+    int rc;
+
+    njb = (struct nmgr_jbuf *) jb;
+
+    if (njb->njb_off + 1 > njb->njb_end) {
+        return '\0';
+    }
+
+    rc = os_mbuf_copydata(njb->njb_in_m, njb->njb_off, 1, &c);
+    if (rc == -1) {
+        c = '\0';
+    }
+    ++njb->njb_off;
+
+    return (c);
+}
+
+static char
+nmgr_jbuf_read_prev(struct json_buffer *jb)
+{
+    struct nmgr_jbuf *njb;
+    char c;
+    int rc;
+
+    njb = (struct nmgr_jbuf *) jb;
+
+    if (njb->njb_off == 0) {
+        return '\0';
+    }
+
+    --njb->njb_off;
+    rc = os_mbuf_copydata(njb->njb_in_m, njb->njb_off, 1, &c);
+    if (rc == -1) {
+        c = '\0';
+    }
+
+    return (c);
+}
+
+static int
+nmgr_jbuf_readn(struct json_buffer *jb, char *buf, int size)
+{
+    struct nmgr_jbuf *njb;
+    int read;
+    int left;
+    int rc;
+
+    njb = (struct nmgr_jbuf *) jb;
+
+    left = njb->njb_end - njb->njb_off;
+    read = size > left ? left : size;
+
+    rc = os_mbuf_copydata(njb->njb_in_m, njb->njb_off, read, buf);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (read);
+err:
+    return (rc);
+}
+
+int
+nmgr_jbuf_write(void *arg, char *data, int len)
+{
+    struct nmgr_jbuf *njb;
+    int rc;
+
+    njb = (struct nmgr_jbuf *) arg;
+
+    rc = nmgr_rsp_extend(njb->njb_hdr, njb->njb_out_m, data, len);
+    if (rc != 0) {
+        assert(0);
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+static int
+nmgr_jbuf_init(struct nmgr_jbuf *njb)
+{
+    memset(njb, 0, sizeof(*njb));
+
+    njb->njb_buf.jb_read_next = nmgr_jbuf_read_next;
+    njb->njb_buf.jb_read_prev = nmgr_jbuf_read_prev;
+    njb->njb_buf.jb_readn = nmgr_jbuf_readn;
+    njb->njb_enc.je_write = nmgr_jbuf_write;
+    njb->njb_enc.je_arg = njb;
+
+    return (0);
+}
+
+static void
+nmgr_jbuf_setibuf(struct nmgr_jbuf *njb, struct os_mbuf *m,
+        uint16_t off, uint16_t len)
+{
+    njb->njb_off = off;
+    njb->njb_end = off + len;
+    njb->njb_in_m = m;
+    njb->njb_enc.je_wr_commas = 0;
+}
+
+static void
+nmgr_jbuf_setobuf(struct nmgr_jbuf *njb, struct nmgr_hdr *hdr,
+        struct os_mbuf *m)
+{
+    njb->njb_out_m = m;
+    njb->njb_hdr = hdr;
+}
+
+void
+nmgr_jbuf_setoerr(struct nmgr_jbuf *njb, int errcode)
+{
+    struct json_value jv;
+
+    json_encode_object_start(&njb->njb_enc);
+    JSON_VALUE_INT(&jv, errcode);
+    json_encode_object_entry(&njb->njb_enc, "rc", &jv);
+    json_encode_object_finish(&njb->njb_enc);
+}
+
+static struct nmgr_hdr*
+nmgr_init_rsp(struct os_mbuf *m, struct nmgr_hdr *src)
+{
+    struct nmgr_hdr *hdr;
+
+    hdr = (struct nmgr_hdr *) os_mbuf_extend(m, sizeof(struct nmgr_hdr));
+    if (!hdr) {
+        return NULL;
+    }
+    memcpy(hdr, src, sizeof(*hdr));
+    hdr->nh_len = 0;
+    hdr->nh_flags = 0;
+    hdr->nh_op = (src->nh_op == NMGR_OP_READ) ? NMGR_OP_READ_RSP :
+      NMGR_OP_WRITE_RSP;
+    hdr->nh_group = src->nh_group;
+    hdr->nh_seq = src->nh_seq;
+    hdr->nh_id = src->nh_id;
+
+    nmgr_jbuf_setobuf(&nmgr_task_jbuf, hdr, m);
+
+    return hdr;
+}
+
+static void
+nmgr_send_err_rsp(struct nmgr_transport *nt, struct os_mbuf *m,
+  struct nmgr_hdr *hdr, int rc)
+{
+    hdr = nmgr_init_rsp(m, hdr);
+    if (!hdr) {
+        return;
+    }
+    nmgr_jbuf_setoerr(&nmgr_task_jbuf, rc);
+    hdr->nh_len = htons(hdr->nh_len);
+    hdr->nh_flags = NMGR_F_JSON_RSP_COMPLETE;
+    nt->nt_output(nt, nmgr_task_jbuf.njb_out_m);
+}
+
+static int
+nmgr_send_rspfrag(struct nmgr_transport *nt, struct nmgr_hdr *rsp_hdr,
+                  struct os_mbuf *rsp, struct os_mbuf *req, uint16_t len,
+                  uint16_t *offset) {
+
+    struct os_mbuf *rspfrag;
+    int rc;
+
+    rspfrag = NULL;
+
+    rspfrag = os_msys_get_pkthdr(len, OS_MBUF_USRHDR_LEN(req));
+    if (!rspfrag) {
+        rc = NMGR_ERR_ENOMEM;
+        goto err;
+    }
+
+    /* Copy the request packet header into the response. */
+    memcpy(OS_MBUF_USRHDR(rspfrag), OS_MBUF_USRHDR(req), 
OS_MBUF_USRHDR_LEN(req));
+
+    if (os_mbuf_append(rspfrag, rsp_hdr, sizeof(struct nmgr_hdr))) {
+        rc = NMGR_ERR_ENOMEM;
+        goto err;
+    }
+
+    if (os_mbuf_appendfrom(rspfrag, rsp, *offset, len)) {
+        rc = NMGR_ERR_ENOMEM;
+        goto err;
+    }
+
+    *offset += len;
+
+    len = htons(len);
+
+    if (os_mbuf_copyinto(rspfrag, offsetof(struct nmgr_hdr, nh_len), &len, 
sizeof(len))) {
+        rc = NMGR_ERR_ENOMEM;
+        goto err;
+    }
+
+    nt->nt_output(nt, rspfrag);
+
+    return NMGR_ERR_EOK;
+err:
+    if (rspfrag) {
+        os_mbuf_free_chain(rspfrag);
+    }
+    return rc;
+}
+
+static int
+nmgr_rsp_fragment(struct nmgr_transport *nt, struct nmgr_hdr *rsp_hdr,
+                  struct os_mbuf *rsp, struct os_mbuf *req) {
+
+    uint16_t offset;
+    uint16_t len;
+    uint16_t mtu;
+    int rc;
+
+    offset = sizeof(struct nmgr_hdr);
+    len = rsp_hdr->nh_len;
+
+    mtu = nt->nt_get_mtu(req) - sizeof(struct nmgr_hdr);
+
+    do {
+        if (len <= mtu) {
+            rsp_hdr->nh_flags |= NMGR_F_JSON_RSP_COMPLETE;
+        } else {
+            len = mtu;
+        }
+
+        rc = nmgr_send_rspfrag(nt, rsp_hdr, rsp, req, len, &offset);
+        if (rc) {
+            goto err;
+        }
+
+        len = rsp_hdr->nh_len - offset + sizeof(struct nmgr_hdr);
+
+    } while (!((rsp_hdr->nh_flags & NMGR_F_JSON_RSP_COMPLETE) ==
+                NMGR_F_JSON_RSP_COMPLETE));
+
+    return NMGR_ERR_EOK;
+err:
+    return rc;
+}
+
+static void
+nmgr_handle_req(struct nmgr_transport *nt, struct os_mbuf *req)
+{
+    struct os_mbuf *rsp;
+    struct nmgr_handler *handler;
+    struct nmgr_hdr *rsp_hdr;
+    struct nmgr_hdr hdr;
+    int off;
+    uint16_t len;
+    int rc;
+
+    rsp_hdr = NULL;
+
+    rsp = os_msys_get_pkthdr(512, OS_MBUF_USRHDR_LEN(req));
+    if (!rsp) {
+        rc = os_mbuf_copydata(req, 0, sizeof(hdr), &hdr);
+        if (rc < 0) {
+            goto err_norsp;
+        }
+        rsp = req;
+        req = NULL;
+        goto err;
+    }
+
+    /* Copy the request packet header into the response. */
+    memcpy(OS_MBUF_USRHDR(rsp), OS_MBUF_USRHDR(req), OS_MBUF_USRHDR_LEN(req));
+
+    off = 0;
+    len = OS_MBUF_PKTHDR(req)->omp_len;
+
+    while (off < len) {
+        rc = os_mbuf_copydata(req, off, sizeof(hdr), &hdr);
+        if (rc < 0) {
+            rc = NMGR_ERR_EINVAL;
+            goto err_norsp;
+        }
+
+        hdr.nh_len = ntohs(hdr.nh_len);
+
+        handler = nmgr_find_handler(ntohs(hdr.nh_group), hdr.nh_id);
+        if (!handler) {
+            rc = NMGR_ERR_ENOENT;
+            goto err;
+        }
+
+        /* Build response header apriori.  Then pass to the handlers
+         * to fill out the response data, and adjust length & flags.
+         */
+        rsp_hdr = nmgr_init_rsp(rsp, &hdr);
+        if (!rsp_hdr) {
+            rc = NMGR_ERR_ENOMEM;
+            goto err_norsp;
+        }
+
+        /*
+         * Setup state for JSON encoding.
+         */
+        nmgr_jbuf_setibuf(&nmgr_task_jbuf, req, off + sizeof(hdr), hdr.nh_len);
+
+        if (hdr.nh_op == NMGR_OP_READ) {
+            if (handler->nh_read) {
+                rc = handler->nh_read(&nmgr_task_jbuf);
+            } else {
+                rc = NMGR_ERR_ENOENT;
+            }
+        } else if (hdr.nh_op == NMGR_OP_WRITE) {
+            if (handler->nh_write) {
+                rc = handler->nh_write(&nmgr_task_jbuf);
+            } else {
+                rc = NMGR_ERR_ENOENT;
+            }
+        } else {
+            rc = NMGR_ERR_EINVAL;
+        }
+
+        if (rc != 0) {
+            goto err;
+        }
+
+        off += sizeof(hdr) + OS_ALIGN(hdr.nh_len, 4);
+        rc = nmgr_rsp_fragment(nt, rsp_hdr, rsp, req);
+        if (rc) {
+            goto err;
+        }
+    }
+
+    os_mbuf_free_chain(rsp);
+    os_mbuf_free_chain(req);
+    return;
+err:
+    OS_MBUF_PKTHDR(rsp)->omp_len = rsp->om_len = 0;
+    nmgr_send_err_rsp(nt, rsp, &hdr, rc);
+    os_mbuf_free_chain(req);
+    return;
+err_norsp:
+    os_mbuf_free_chain(rsp);
+    os_mbuf_free_chain(req);
+    return;
+}
+
+
+void
+nmgr_process(struct nmgr_transport *nt)
+{
+    struct os_mbuf *m;
+
+    while (1) {
+        m = os_mqueue_get(&nt->nt_imq);
+        if (!m) {
+            break;
+        }
+
+        nmgr_handle_req(nt, m);
+    }
+}
+
+void
+nmgr_task(void *arg)
+{
+    struct nmgr_transport *nt;
+    struct os_event *ev;
+    struct os_callout_func *ocf;
+
+    nmgr_jbuf_init(&nmgr_task_jbuf);
+
+    while (1) {
+        ev = os_eventq_get(&g_nmgr_evq);
+        switch (ev->ev_type) {
+            case OS_EVENT_T_MQUEUE_DATA:
+                nt = (struct nmgr_transport *) ev->ev_arg;
+                nmgr_process(nt);
+                break;
+           case OS_EVENT_T_TIMER:
+               ocf = (struct os_callout_func *)ev;
+               ocf->cf_func(CF_ARG(ocf));
+               break;
+        }
+    }
+}
+
+int
+nmgr_transport_init(struct nmgr_transport *nt,
+        nmgr_transport_out_func_t output_func,
+        nmgr_transport_get_mtu_func_t get_mtu_func)
+{
+    int rc;
+
+    nt->nt_output = output_func;
+    nt->nt_get_mtu = get_mtu_func;
+
+    rc = os_mqueue_init(&nt->nt_imq, nt);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Transfers an incoming request to the newtmgr task.  The caller relinquishes
+ * ownership of the supplied mbuf upon calling this function, whether this
+ * function succeeds or fails.
+ *
+ * @param nt                    The transport that the request was received
+ *                                  over.
+ * @param req                   An mbuf containing the newtmgr request.
+ *
+ * @return                      0 on success; nonzero on failure.
+ */
+int
+nmgr_rx_req(struct nmgr_transport *nt, struct os_mbuf *req)
+{
+    int rc;
+
+    rc = os_mqueue_put(&nt->nt_imq, &g_nmgr_evq, req);
+    if (rc != 0) {
+        os_mbuf_free_chain(req);
+    }
+
+    return rc;
+}
+
+static uint16_t
+nmgr_shell_get_mtu(struct os_mbuf *m) {
+    return NMGR_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:
+    return (rc);
+}
+
+static int
+nmgr_shell_in(struct os_mbuf *m, void *arg)
+{
+    struct nmgr_transport *nt;
+    int rc;
+
+    nt = (struct nmgr_transport *) arg;
+
+    rc = os_mqueue_put(&nt->nt_imq, &g_nmgr_evq, m);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+int
+nmgr_task_init(void)
+{
+    int rc;
+
+    os_eventq_init(&g_nmgr_evq);
+
+    rc = nmgr_transport_init(&g_nmgr_shell_transport, nmgr_shell_out,
+                             nmgr_shell_get_mtu);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = shell_nlip_input_register(nmgr_shell_in,
+            (void *) &g_nmgr_shell_transport);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = os_task_init(&g_nmgr_task, "newtmgr", nmgr_task, NULL,
+      MYNEWT_VAL(NEWTMGR_TASK_PRIO), OS_WAIT_FOREVER,
+      newtmgr_stack, OS_STACK_ALIGN(MYNEWT_VAL(NEWTMGR_STACK_SIZE)));
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = nmgr_os_groups_register(&g_nmgr_evq);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+void
+nmgr_pkg_init(void)
+{
+    int rc;
+
+    rc = nmgr_task_init();
+    SYSINIT_PANIC_ASSERT(rc == 0);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/newtmgr/syscfg.yml
----------------------------------------------------------------------
diff --git a/mgmt/newtmgr/syscfg.yml b/mgmt/newtmgr/syscfg.yml
new file mode 100644
index 0000000..07a7f1a
--- /dev/null
+++ b/mgmt/newtmgr/syscfg.yml
@@ -0,0 +1,13 @@
+# Package: mgmt/newtmgr
+
+syscfg.defs:
+    NEWTMGR_TASK_PRIO:
+        description: 'TBD'
+        type: 'task_priority'
+        value: 'any'
+    NEWTMGR_STACK_SIZE:
+        description: 'TBD'
+        value: 512
+    NEWTMGR_BLE_HOST:
+        description: 'TBD'
+        value: 0

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/newtmgr/transport/ble/include/nmgrble/newtmgr_ble.h
----------------------------------------------------------------------
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..252cb5f
--- /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 */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/newtmgr/transport/ble/pkg.yml
----------------------------------------------------------------------
diff --git a/mgmt/newtmgr/transport/ble/pkg.yml 
b/mgmt/newtmgr/transport/ble/pkg.yml
new file mode 100644
index 0000000..45c71e1
--- /dev/null
+++ b/mgmt/newtmgr/transport/ble/pkg.yml
@@ -0,0 +1,33 @@
+#
+# 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 <d...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/";
+pkg.keywords:
+    - ble
+    - bluetooth
+
+pkg.deps:
+    - kernel/os
+    - net/nimble/host
+
+pkg.init_function: newtmgr_ble_pkg_init
+pkg.init_stage: 5

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/newtmgr/transport/ble/src/newtmgr_ble.c
----------------------------------------------------------------------
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..817673d
--- /dev/null
+++ b/mgmt/newtmgr/transport/ble/src/newtmgr_ble.c
@@ -0,0 +1,261 @@
+/**
+ * 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 "newtmgr/newtmgr.h"
+#include "os/endian.h"
+#include "console/console.h"
+
+/* nmgr ble mqueue */
+struct os_mqueue ble_nmgr_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} */
+const uint8_t gatt_svr_svc_newtmgr[16] = {
+    0x84, 0xaa, 0x60, 0x74, 0x52, 0x8a, 0x8b, 0x86,
+    0xd3, 0x4c, 0xb7, 0x1d, 0x1d, 0xdc, 0x53, 0x8d
+};
+
+/* {DA2E7828-FBCE-4E01-AE9E-261174997C48} */
+const uint8_t gatt_svr_chr_newtmgr[16] = {
+    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,
+        .uuid128 = (void *)gatt_svr_svc_newtmgr,
+        .characteristics = (struct ble_gatt_chr_def[]) { {
+            /* Characteristic: Write No Rsp */
+            .uuid128 = (void *)gatt_svr_chr_newtmgr,
+            .access_cb = gatt_svr_chr_access_newtmgr,
+            .flags = BLE_GATT_CHR_F_WRITE_NO_RSP,
+            .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) {
+        assert(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
+ */
+
+int
+nmgr_ble_proc_mq_evt(struct os_event *ev)
+{
+    struct os_mbuf *m_resp;
+    uint16_t conn_handle;
+    int rc;
+
+    rc = 0;
+    switch (ev->ev_type) {
+        case OS_EVENT_T_MQUEUE_DATA:
+            if (ev->ev_arg != &ble_nmgr_mq) {
+                rc = -1;
+                goto done;
+            }
+
+            while (1) {
+                m_resp = os_mqueue_get(&ble_nmgr_mq);
+                if (!m_resp) {
+                    break;
+                }
+                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);
+            }
+            break;
+
+        default:
+            rc = -1;
+            goto done;
+    }
+
+done:
+    return rc;
+}
+
+static int
+nmgr_ble_out(struct nmgr_transport *nt, struct os_mbuf *m)
+{
+    int rc;
+
+    rc = os_mqueue_put(&ble_nmgr_mq, ble_hs_cfg.parent_evq, m);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    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(&ble_nmgr_mq, &ble_nmgr_mq);
+
+    rc = nmgr_transport_init(&ble_nt, nmgr_ble_out, nmgr_ble_get_mtu);
+
+err:
+    return rc;
+}
+
+void
+newtmgr_ble_pkg_init(void)
+{
+    int rc;
+
+    rc = nmgr_ble_gatt_svr_init();
+    SYSINIT_PANIC_ASSERT(rc == 0);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/oicmgr/include/newtmgr/newtmgr.h
----------------------------------------------------------------------
diff --git a/mgmt/oicmgr/include/newtmgr/newtmgr.h 
b/mgmt/oicmgr/include/newtmgr/newtmgr.h
new file mode 100644
index 0000000..32d16e5
--- /dev/null
+++ b/mgmt/oicmgr/include/newtmgr/newtmgr.h
@@ -0,0 +1,120 @@
+/**
+ * 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 <json/json.h>
+#include <inttypes.h>
+#include <os/os.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* MTU for newtmgr responses */
+#define NMGR_MAX_MTU 1024
+
+#ifndef STR
+/* Stringification of constants */
+#define STR(x) #x
+#endif
+
+/* First 64 groups are reserved for system level newtmgr commands.
+ * Per-user commands are then defined after group 64.
+ */
+#define NMGR_GROUP_ID_DEFAULT   (0)
+#define NMGR_GROUP_ID_IMAGE     (1)
+#define NMGR_GROUP_ID_STATS     (2)
+#define NMGR_GROUP_ID_CONFIG    (3)
+#define NMGR_GROUP_ID_LOGS      (4)
+#define NMGR_GROUP_ID_CRASH     (5)
+#define NMGR_GROUP_ID_SPLIT     (6)
+#define NMGR_GROUP_ID_PERUSER   (64)
+
+#define NMGR_OP_READ            (0)
+#define NMGR_OP_READ_RSP        (1)
+#define NMGR_OP_WRITE           (2)
+#define NMGR_OP_WRITE_RSP       (3)
+
+
+/**
+ * Newtmgr JSON error codes
+ */
+#define NMGR_ERR_EOK      (0)
+#define NMGR_ERR_EUNKNOWN (1)
+#define NMGR_ERR_ENOMEM   (2)
+#define NMGR_ERR_EINVAL   (3)
+#define NMGR_ERR_ETIMEOUT (4)
+#define NMGR_ERR_ENOENT   (5)
+#define NMGR_ERR_EPERUSER (256)
+
+struct nmgr_hdr {
+    uint8_t  nh_op;             /* NMGR_OP_XXX */
+    uint8_t  nh_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 */
+};
+
+struct nmgr_jbuf {
+    /* json_buffer must be first element in the structure */
+    struct json_buffer njb_buf;
+    struct json_encoder njb_enc;
+    char *njb_in;
+    uint16_t njb_in_off;
+    uint16_t njb_in_end;
+    char *njb_out;
+    uint16_t njb_out_off;
+    uint16_t njb_out_end;
+};
+int nmgr_jbuf_setoerr(struct nmgr_jbuf *njb, int errcode);
+
+typedef int (*nmgr_handler_func_t)(struct nmgr_jbuf *);
+
+#define NMGR_HANDLER_FUNC(__name)                                           \
+    int __name(struct nmgr_hdr *nmr, struct os_mbuf *req, uint16_t srcoff,  \
+            struct os_mbuf *rsp)
+
+struct nmgr_handler {
+    nmgr_handler_func_t nh_read;
+    nmgr_handler_func_t nh_write;
+};
+
+struct nmgr_group {
+    struct nmgr_handler *ng_handlers;
+    uint16_t ng_handlers_count;
+    uint16_t ng_group_id;
+    STAILQ_ENTRY(nmgr_group) ng_next;
+};
+
+#define NMGR_GROUP_SET_HANDLERS(__group, __handlers)       \
+    (__group)->ng_handlers = (__handlers);                 \
+    (__group)->ng_handlers_count = (sizeof((__handlers)) / \
+            sizeof(struct nmgr_handler));
+
+int nmgr_oic_init(uint8_t, os_stack_t *, uint16_t);
+int nmgr_group_register(struct nmgr_group *group);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NETMGR_H */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/oicmgr/pkg.yml
----------------------------------------------------------------------
diff --git a/mgmt/oicmgr/pkg.yml b/mgmt/oicmgr/pkg.yml
new file mode 100644
index 0000000..5458034
--- /dev/null
+++ b/mgmt/oicmgr/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/oicmgr
+pkg.description: Server-side newtmgr functionality for OIC
+pkg.author: "Apache Mynewt <d...@mynewt.incubator.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/";
+pkg.keywords:
+
+pkg.deps:
+    - kernel/os
+    - net/oic
+    - encoding/json
+    - mgmt/newtmgr/nmgr_os
+    - libs/util
+    - test/testutil
+    - sys/shell
+    - sys/reboot
+
+pkg.cflags:
+    - -DOC_SERVER
+
+pkg.apis:
+    - newtmgr

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/oicmgr/src/newtmgr.c
----------------------------------------------------------------------
diff --git a/mgmt/oicmgr/src/newtmgr.c b/mgmt/oicmgr/src/newtmgr.c
new file mode 100644
index 0000000..136545f
--- /dev/null
+++ b/mgmt/oicmgr/src/newtmgr.c
@@ -0,0 +1,500 @@
+/**
+ * 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 <os/os.h>
+#include <os/endian.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <newtmgr/newtmgr.h>
+#include <nmgr_os/nmgr_os.h>
+
+#include <oic/oc_api.h>
+
+#define NMGR_OC_EVENT  (OS_EVENT_T_PERUSER)
+#define NMGR_OC_TIMER  (OS_EVENT_T_PERUSER + 1)
+
+struct nmgr_state {
+    struct os_mutex ns_group_lock;
+    STAILQ_HEAD(, nmgr_group) ns_groups;
+    struct os_eventq ns_evq;
+    struct os_event ns_oc_event;
+    struct os_callout ns_oc_timer;
+    struct os_task ns_task;
+    struct nmgr_jbuf ns_jbuf;          /* JSON buffer for NMGR task */
+    char ns_rsp[NMGR_MAX_MTU];
+};
+
+static struct nmgr_state nmgr_state = {
+  .ns_groups = STAILQ_HEAD_INITIALIZER(nmgr_state.ns_groups),
+  .ns_oc_event.ev_type = NMGR_OC_EVENT,
+  .ns_oc_timer.c_ev.ev_type = NMGR_OC_TIMER,
+  .ns_oc_timer.c_evq = &nmgr_state.ns_evq
+};
+
+static void nmgr_oic_get(oc_request_t *request, oc_interface_mask_t interface);
+static void nmgr_oic_put(oc_request_t *request, oc_interface_mask_t interface);
+
+int
+nmgr_group_list_lock(void)
+{
+    int rc;
+
+    if (!os_started()) {
+        return (0);
+    }
+
+    rc = os_mutex_pend(&nmgr_state.ns_group_lock, OS_WAIT_FOREVER);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+int
+nmgr_group_list_unlock(void)
+{
+    int rc;
+
+    if (!os_started()) {
+        return (0);
+    }
+
+    rc = os_mutex_release(&nmgr_state.ns_group_lock);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+int
+nmgr_group_register(struct nmgr_group *group)
+{
+    int rc;
+
+    rc = nmgr_group_list_lock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    STAILQ_INSERT_TAIL(&nmgr_state.ns_groups, group, ng_next);
+
+    rc = nmgr_group_list_unlock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+static struct nmgr_group *
+nmgr_find_group(uint16_t group_id)
+{
+    struct nmgr_group *group;
+    int rc;
+
+    group = NULL;
+
+    rc = nmgr_group_list_lock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    STAILQ_FOREACH(group, &nmgr_state.ns_groups, ng_next) {
+        if (group->ng_group_id == group_id) {
+            break;
+        }
+    }
+
+    rc = nmgr_group_list_unlock();
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (group);
+err:
+    return (NULL);
+}
+
+static struct nmgr_handler *
+nmgr_find_handler(uint16_t group_id, uint16_t handler_id)
+{
+    struct nmgr_group *group;
+    struct nmgr_handler *handler;
+
+    group = nmgr_find_group(group_id);
+    if (!group) {
+        goto err;
+    }
+
+    if (handler_id >= group->ng_handlers_count) {
+        goto err;
+    }
+
+    handler = &group->ng_handlers[handler_id];
+
+    return (handler);
+err:
+    return (NULL);
+}
+
+int
+nmgr_rsp_extend(struct nmgr_hdr *hdr, struct os_mbuf *rsp, void *data,
+        uint16_t len)
+{
+    int rc;
+
+    rc = os_mbuf_append(rsp, data, len);
+    if (rc != 0) {
+        goto err;
+    }
+    hdr->nh_len += len;
+
+    return (0);
+err:
+    return (rc);
+}
+
+static char
+nmgr_jbuf_read_next(struct json_buffer *jb)
+{
+    struct nmgr_jbuf *njb;
+    char c;
+
+    njb = (struct nmgr_jbuf *) jb;
+
+    if (njb->njb_in_off + 1 > njb->njb_in_end) {
+        return '\0';
+    }
+
+    c = njb->njb_in[njb->njb_in_off];
+    ++njb->njb_in_off;
+
+    return (c);
+}
+
+static char
+nmgr_jbuf_read_prev(struct json_buffer *jb)
+{
+    struct nmgr_jbuf *njb;
+    char c;
+
+    njb = (struct nmgr_jbuf *) jb;
+
+    if (njb->njb_in_off == 0) {
+        return '\0';
+    }
+
+    --njb->njb_in_off;
+    c = njb->njb_in[njb->njb_in_off];
+
+    return (c);
+}
+
+static int
+nmgr_jbuf_readn(struct json_buffer *jb, char *buf, int size)
+{
+    struct nmgr_jbuf *njb;
+    int read;
+    int left;
+
+    njb = (struct nmgr_jbuf *) jb;
+
+    left = njb->njb_in_end - njb->njb_in_off;
+    read = size > left ? left : size;
+
+    memcpy(buf, njb->njb_in + njb->njb_in_off, read);
+
+    return (read);
+}
+
+static int
+nmgr_jbuf_write(void *arg, char *data, int len)
+{
+    struct nmgr_jbuf *njb;
+    int rc;
+
+    njb = (struct nmgr_jbuf *) arg;
+
+    if (njb->njb_out_off + len >= njb->njb_out_end) {
+        assert(0);
+        goto err;
+    }
+    memcpy(njb->njb_out + njb->njb_out_off, data, len);
+    njb->njb_out_off += len;
+    njb->njb_out[njb->njb_out_off] = '\0';
+
+    return (0);
+err:
+    return (rc);
+}
+
+static void
+nmgr_jbuf_init(struct nmgr_jbuf *njb)
+{
+    memset(njb, 0, sizeof(*njb));
+
+    njb->njb_buf.jb_read_next = nmgr_jbuf_read_next;
+    njb->njb_buf.jb_read_prev = nmgr_jbuf_read_prev;
+    njb->njb_buf.jb_readn = nmgr_jbuf_readn;
+    njb->njb_enc.je_write = nmgr_jbuf_write;
+    njb->njb_enc.je_arg = njb;
+}
+
+static void
+nmgr_jbuf_setibuf(struct nmgr_jbuf *njb, char *ptr, uint16_t len)
+{
+    njb->njb_in_off = 0;
+    njb->njb_in_end = len;
+    njb->njb_in = ptr;
+    njb->njb_enc.je_wr_commas = 0;
+}
+
+static void
+nmgr_jbuf_setobuf(struct nmgr_jbuf *njb, char *ptr, uint16_t maxlen)
+{
+    njb->njb_out = ptr;
+    njb->njb_out_off = 0;
+    njb->njb_out_end = maxlen;
+    njb->njb_out[0] = '\0';
+}
+
+int
+nmgr_jbuf_setoerr(struct nmgr_jbuf *njb, int errcode)
+{
+    struct json_value jv;
+
+    json_encode_object_start(&njb->njb_enc);
+    JSON_VALUE_INT(&jv, errcode);
+    json_encode_object_entry(&njb->njb_enc, "rc", &jv);
+    json_encode_object_finish(&njb->njb_enc);
+
+    return (0);
+}
+
+static struct nmgr_handler *
+nmgr_oic_find_handler(const char *q, int qlen)
+{
+    int grp = -1;
+    int id = -1;
+    char *str;
+    char *eptr;
+    int slen;
+
+    slen = oc_ri_get_query_value(q, qlen, "gr", &str);
+    if (slen > 0) {
+        grp = strtoul(str, &eptr, 0);
+        if (*eptr != '\0' && *eptr != '&') {
+            return NULL;
+        }
+    }
+    slen = oc_ri_get_query_value(q, qlen, "id", &str);
+    if (slen > 0) {
+        id = strtoul(str, &eptr, 0);
+        if (*eptr != '\0' && *eptr != '&') {
+            return NULL;
+        }
+    }
+    return nmgr_find_handler(grp, id);
+}
+
+static void
+nmgr_oic_op(oc_request_t *req, oc_interface_mask_t mask, int isset)
+{
+    struct nmgr_state *ns = &nmgr_state;
+    struct nmgr_handler *handler;
+    oc_rep_t *data;
+    int rc;
+
+    if (!req->query_len) {
+        goto bad_req;
+    }
+
+    handler = nmgr_oic_find_handler(req->query, req->query_len);
+    if (!handler) {
+        goto bad_req;
+    }
+
+    /*
+     * Setup state for JSON encoding.
+     */
+    nmgr_jbuf_setobuf(&ns->ns_jbuf, ns->ns_rsp, sizeof(ns->ns_rsp));
+
+    data = req->request_payload;
+    if (data) {
+        if (data->type != STRING) {
+            goto bad_req;
+        }
+        nmgr_jbuf_setibuf(&ns->ns_jbuf, oc_string(data->value_string),
+          oc_string_len(data->value_string));
+    } else {
+        nmgr_jbuf_setibuf(&ns->ns_jbuf, NULL, 0);
+    }
+
+    if (!isset) {
+        if (handler->nh_read) {
+            rc = handler->nh_read(&ns->ns_jbuf);
+        } else {
+            goto bad_req;
+        }
+    } else {
+        if (handler->nh_write) {
+            rc = handler->nh_write(&ns->ns_jbuf);
+        } else {
+            goto bad_req;
+        }
+    }
+    if (rc) {
+        goto bad_req;
+    }
+
+    oc_rep_start_root_object();
+    switch (mask) {
+    case OC_IF_BASELINE:
+        oc_process_baseline_interface(req->resource);
+    case OC_IF_RW:
+        oc_rep_set_text_string(root, "key", ns->ns_rsp);
+        break;
+    default:
+        break;
+    }
+    oc_rep_end_root_object();
+    oc_send_response(req, OC_STATUS_OK);
+
+    return;
+bad_req:
+    oc_send_response(req, OC_STATUS_BAD_REQUEST);
+}
+
+static void
+nmgr_oic_get(oc_request_t *req, oc_interface_mask_t mask)
+{
+    nmgr_oic_op(req, mask, 0);
+}
+
+static void
+nmgr_oic_put(oc_request_t *req, oc_interface_mask_t mask)
+{
+    nmgr_oic_op(req, mask, 1);
+}
+
+static void
+nmgr_app_init(void)
+{
+    oc_init_platform("MyNewt", NULL, NULL);
+    oc_add_device("/oic/d", "oic.d.light", "MynewtLed", "1.0", "1.0", NULL,
+      NULL);
+}
+
+static void
+nmgr_register_resources(void)
+{
+    uint8_t mode;
+    oc_resource_t *res = NULL;
+    char name[12];
+
+    snprintf(name, sizeof(name), "/nmgr");
+    res = oc_new_resource(name, 1, 0);
+    oc_resource_bind_resource_type(res, "x.mynewt.nmgr");
+    mode = OC_IF_RW;
+    oc_resource_bind_resource_interface(res, mode);
+    oc_resource_set_default_interface(res, mode);
+    oc_resource_set_discoverable(res);
+    oc_resource_set_request_handler(res, OC_GET, nmgr_oic_get);
+    oc_resource_set_request_handler(res, OC_PUT, nmgr_oic_put);
+    oc_add_resource(res);
+}
+
+static const oc_handler_t nmgr_oc_handler = {
+    .init = nmgr_app_init,
+    .register_resources = nmgr_register_resources
+};
+
+void
+oc_signal_main_loop(void)
+{
+    struct nmgr_state *ns = &nmgr_state;
+
+    os_eventq_put(&ns->ns_evq, &ns->ns_oc_event);
+}
+
+void
+nmgr_oic_task(void *arg)
+{
+    struct nmgr_state *ns = &nmgr_state;
+    struct os_event *ev;
+    struct os_callout_func *ocf;
+    os_time_t next_event;
+
+    nmgr_jbuf_init(&ns->ns_jbuf);
+
+    oc_main_init((oc_handler_t *)&nmgr_oc_handler);
+    while (1) {
+        ev = os_eventq_get(&ns->ns_evq);
+        switch (ev->ev_type) {
+        case NMGR_OC_EVENT:
+        case NMGR_OC_TIMER:
+            next_event = oc_main_poll();
+            if (next_event) {
+                os_callout_reset(&ns->ns_oc_timer, next_event - os_time_get());
+            } else {
+                os_callout_stop(&ns->ns_oc_timer);
+            }
+            break;
+        case OS_EVENT_T_TIMER:
+            ocf = (struct os_callout_func *)ev;
+            ocf->cf_func(CF_ARG(ocf));
+            break;
+        }
+    }
+}
+
+int
+nmgr_oic_init(uint8_t prio, os_stack_t *stack_ptr, uint16_t stack_len)
+{
+    struct nmgr_state *ns = &nmgr_state;
+    int rc;
+
+    os_eventq_init(&ns->ns_evq);
+
+    rc = os_task_init(&ns->ns_task, "newtmgr_oic", nmgr_oic_task, NULL, prio,
+            OS_WAIT_FOREVER, stack_ptr, stack_len);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = nmgr_os_groups_register(&ns->ns_evq);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/mgmt/oicmgr/syscfg.yml
----------------------------------------------------------------------
diff --git a/mgmt/oicmgr/syscfg.yml b/mgmt/oicmgr/syscfg.yml
new file mode 100644
index 0000000..5bf2332
--- /dev/null
+++ b/mgmt/oicmgr/syscfg.yml
@@ -0,0 +1,10 @@
+# Package: mgmt/newtmgr_oic
+
+syscfg.defs:
+    ### These should be renamed with a proper prefix.
+    NEWTMGR:
+        description: 'TBD'
+        value: 1
+    OC_SERVER:
+        description: 'TBD'
+        value: 1

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/b99324aa/test/crash_test/pkg.yml
----------------------------------------------------------------------
diff --git a/test/crash_test/pkg.yml b/test/crash_test/pkg.yml
index b9ca425..c2ec845 100644
--- a/test/crash_test/pkg.yml
+++ b/test/crash_test/pkg.yml
@@ -30,7 +30,6 @@ pkg.req_apis.CRASH_TEST_NEWTMGR:
     - newtmgr
 
 pkg.deps.CRASH_TEST_NEWTMGR:
-    - libs/newtmgr
     - encoding/json
 
 pkg.init_function: crash_test_init

Reply via email to