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/13 18:47:48 UTC
[mynewt-mcumgr] branch master updated: Initial implementation: mgmt, newtmgr
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
The following commit(s) were added to refs/heads/master by this push:
new 46c0a53 Initial implementation: mgmt, newtmgr
46c0a53 is described below
commit 46c0a53084f1b1c7007abe322d110c75c8fa0828
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Thu Dec 7 17:03:11 2017 -0800
Initial implementation: mgmt, newtmgr
---
.gitignore | 37 +++
mgmt/include/mgmt/mgmt.h | 166 ++++++++++
mgmt/pkg.yml | 29 ++
mgmt/port/mynewt/include/mynewt_mgmt/mynewt_mgmt.h | 37 +++
mgmt/port/mynewt/pkg.yml | 27 ++
mgmt/src/mgmt.c | 156 +++++++++
mgmt/syscfg.yml | 18 ++
newtmgr/include/newtmgr/newtmgr.h | 48 +++
newtmgr/pkg.yml | 41 +++
.../mynewt/include/mynewt_newtmgr/mynewt_newtmgr.h | 66 ++++
newtmgr/port/mynewt/pkg.yml | 30 ++
newtmgr/port/mynewt/src/mynewt_nmgr.c | 273 ++++++++++++++++
newtmgr/src/newtmgr.c | 353 +++++++++++++++++++++
13 files changed, 1281 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/include/mgmt/mgmt.h b/mgmt/include/mgmt/mgmt.h
new file mode 100644
index 0000000..b2c5dd1
--- /dev/null
+++ b/mgmt/include/mgmt/mgmt.h
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_MGMT_MGMT_
+#define H_MGMT_MGMT_
+
+#include <inttypes.h>
+
+#include "tinycbor/cbor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* MTU for newtmgr responses */
+#define MGMT_MAX_MTU 1024
+
+#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_OS (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; /* 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 void *mgmt_alloc_rsp_fn(const void *req, void *arg);
+typedef int mgmt_trim_front_fn(void *buf, int len, void *arg);
+typedef void mgmt_reset_buf_fn(void *buf, void *arg);
+typedef int mgmt_write_at_fn(struct cbor_encoder_writer *writer, int offset,
+ const void *data, int len, void *arg);
+typedef int mgmt_init_reader_fn(struct cbor_decoder_reader *reader, void *buf,
+ void *arg);
+typedef int mgmt_init_writer_fn(struct cbor_encoder_writer *writer, void *buf,
+ void *arg);
+typedef void mgmt_free_buf_fn(void *buf, void *arg);
+
+struct mgmt_streamer_cfg {
+ mgmt_alloc_rsp_fn *alloc_rsp;
+ mgmt_trim_front_fn *trim_front;
+ mgmt_reset_buf_fn *reset_buf;
+ mgmt_write_at_fn *write_at;
+ mgmt_init_reader_fn *init_reader;
+ mgmt_init_writer_fn *init_writer;
+ mgmt_free_buf_fn *free_buf;
+};
+
+/** Decodes requests and encodes responses. */
+struct mgmt_streamer {
+ const struct mgmt_streamer_cfg *cfg;
+ void *cb_arg;
+ struct cbor_decoder_reader *reader;
+ struct cbor_encoder_writer *writer;
+};
+
+/**
+ * Context required by command handlers for parsing requests and writing
+ * responses.
+ */
+struct mgmt_cbuf {
+ struct CborEncoder encoder;
+ struct CborParser parser;
+ struct CborValue it;
+};
+
+typedef int mgmt_handler_fn(struct mgmt_cbuf *cbuf);
+
+/** Read and write handlers for a single command ID. */
+struct mgmt_handler {
+ mgmt_handler_fn *mh_read;
+ mgmt_handler_fn *mh_write;
+};
+
+/** A collection of handlers for every command in a single group. */
+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__) do { \
+ (group__)->mg_handlers = (handlers__); \
+ (group__)->mg_handlers_count = \
+ sizeof (handlers__) / sizeof (handlers__)[0]; \
+} while (0)
+
+void *mgmt_streamer_alloc_rsp(struct mgmt_streamer *streamer, const void *req);
+int mgmt_streamer_trim_front(struct mgmt_streamer *streamer, void *buf,
+ int len);
+void mgmt_streamer_reset_buf(struct mgmt_streamer *streamer, void *buf);
+int mgmt_streamer_write_at(struct mgmt_streamer *streamer, int offset,
+ const void *data, int len);
+int mgmt_streamer_init_reader(struct mgmt_streamer *streamer, void *buf);
+int mgmt_streamer_init_writer(struct mgmt_streamer *streamer, void *buf);
+void mgmt_streamer_free_buf(struct mgmt_streamer *streamer, void *buf);
+
+int mgmt_group_register(struct mgmt_group *group);
+int mgmt_cbuf_setoerr(struct mgmt_cbuf *cbuf, int errcode);
+const struct mgmt_handler *mgmt_find_handler(uint16_t group_id,
+ uint16_t command_id);
+int mgmt_err_from_cbor(int cbor_status);
+int mgmt_cbuf_init(struct mgmt_cbuf *cbuf, struct mgmt_streamer *streamer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MGMT_MGMT_H_ */
diff --git a/mgmt/pkg.yml b/mgmt/pkg.yml
new file mode 100644
index 0000000..7059910
--- /dev/null
+++ b/mgmt/pkg.yml
@@ -0,0 +1,29 @@
+#
+# 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:
+ - encoding/tinycbor
+ - kernel/os
+ - mgmt/mgmt/port/mynewt
diff --git a/mgmt/port/mynewt/include/mynewt_mgmt/mynewt_mgmt.h b/mgmt/port/mynewt/include/mynewt_mgmt/mynewt_mgmt.h
new file mode 100644
index 0000000..2dfaa2c
--- /dev/null
+++ b/mgmt/port/mynewt/include/mynewt_mgmt/mynewt_mgmt.h
@@ -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.
+ */
+
+#ifndef H_MYNEWT_MGMT_
+#define H_MYNEWT_MGMT_
+
+#include "mgmt/mgmt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_eventq *mgmt_evq_get(void);
+void mgmt_evq_set(struct os_eventq *evq);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/mgmt/port/mynewt/pkg.yml b/mgmt/port/mynewt/pkg.yml
new file mode 100644
index 0000000..048acfc
--- /dev/null
+++ b/mgmt/port/mynewt/pkg.yml
@@ -0,0 +1,27 @@
+#
+# 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/port/mynewt
+pkg.description: XXX
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - kernel/os
diff --git a/mgmt/src/mgmt.c b/mgmt/src/mgmt.c
new file mode 100644
index 0000000..1acb60f
--- /dev/null
+++ b/mgmt/src/mgmt.c
@@ -0,0 +1,156 @@
+/*
+ * 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 "tinycbor/cbor.h"
+#include "mgmt/mgmt.h"
+
+static struct mgmt_group *mgmt_group_list;
+static struct mgmt_group *mgmt_group_list_end;
+
+void *
+mgmt_streamer_alloc_rsp(struct mgmt_streamer *streamer, const void *req)
+{
+ return streamer->cfg->alloc_rsp(req, streamer->cb_arg);
+}
+
+int
+mgmt_streamer_trim_front(struct mgmt_streamer *streamer, void *buf, int len)
+{
+ return streamer->cfg->trim_front(buf, len, streamer->cb_arg);
+}
+
+void
+mgmt_streamer_reset_buf(struct mgmt_streamer *streamer, void *buf)
+{
+ streamer->cfg->reset_buf(buf, streamer->cb_arg);
+}
+
+int
+mgmt_streamer_write_at(struct mgmt_streamer *streamer, int offset,
+ const void *data, int len)
+{
+ return streamer->cfg->write_at(streamer->writer, offset, data, len,
+ streamer->cb_arg);
+}
+
+int
+mgmt_streamer_init_reader(struct mgmt_streamer *streamer, void *buf)
+{
+ return streamer->cfg->init_reader(streamer->reader, buf, streamer->cb_arg);
+}
+
+int
+mgmt_streamer_init_writer(struct mgmt_streamer *streamer, void *buf)
+{
+ return streamer->cfg->init_writer(streamer->writer, buf, streamer->cb_arg);
+}
+
+void
+mgmt_streamer_free_buf(struct mgmt_streamer *streamer, void *buf)
+{
+ streamer->cfg->free_buf(buf, streamer->cb_arg);
+}
+
+int
+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;
+
+ return 0;
+}
+
+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 command_id)
+{
+ const struct mgmt_group *group;
+
+ group = mgmt_find_group(group_id);
+ if (group == NULL) {
+ return NULL;
+ }
+
+ if (command_id >= group->mg_handlers_count) {
+ return NULL;
+ }
+
+ return &group->mg_handlers[command_id];
+}
+
+int
+mgmt_cbuf_setoerr(struct mgmt_cbuf *cbuf, int errcode)
+{
+ int rc;
+
+ rc = cbor_encode_text_stringz(&cbuf->encoder, "rc");
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = cbor_encode_int(&cbuf->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_streamer *streamer)
+{
+ int rc;
+
+ rc = cbor_parser_init(streamer->reader, 0, &cbuf->parser, &cbuf->it);
+ if (rc != CborNoError) {
+ return mgmt_err_from_cbor(rc);
+ }
+
+ cbor_encoder_init(&cbuf->encoder, streamer->writer, 0);
+
+ return 0;
+}
diff --git a/mgmt/syscfg.yml b/mgmt/syscfg.yml
new file mode 100644
index 0000000..30ccc02
--- /dev/null
+++ b/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/newtmgr/include/newtmgr/newtmgr.h b/newtmgr/include/newtmgr/newtmgr.h
new file mode 100644
index 0000000..23ae190
--- /dev/null
+++ b/newtmgr/include/newtmgr/newtmgr.h
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _NEWTMGR_H_
+#define _NEWTMGR_H_
+
+#include "mgmt/mgmt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct mynewt_nmgr_transport;
+struct nmgr_streamer;
+struct nmgr_hdr;
+typedef int nmgr_tx_rsp_fn(struct nmgr_streamer *ns, void *buf, void *arg);
+
+struct nmgr_streamer {
+ struct mgmt_streamer ns_base;
+ nmgr_tx_rsp_fn *ns_tx_rsp;
+};
+
+void nmgr_ntoh_hdr(struct nmgr_hdr *hdr);
+int nmgr_handle_single_payload(struct mgmt_cbuf *cbuf,
+ const struct nmgr_hdr *req_hdr);
+int nmgr_process_single_packet(struct nmgr_streamer *streamer, void *req);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NETMGR_H */
diff --git a/newtmgr/pkg.yml b/newtmgr/pkg.yml
new file mode 100644
index 0000000..2d48007
--- /dev/null
+++ b/newtmgr/pkg.yml
@@ -0,0 +1,41 @@
+#
+# 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
+ - mgmt/newtmgr/port/mynewt
+ - util/mem
+
+pkg.deps.NEWTMGR_BLE_HOST:
+ - mgmt/newtmgr/transport/ble
+
+pkg.apis:
+ - newtmgr
+
+pkg.init:
+ nmgr_pkg_init: 500
diff --git a/newtmgr/port/mynewt/include/mynewt_newtmgr/mynewt_newtmgr.h b/newtmgr/port/mynewt/include/mynewt_newtmgr/mynewt_newtmgr.h
new file mode 100644
index 0000000..0317ef5
--- /dev/null
+++ b/newtmgr/port/mynewt/include/mynewt_newtmgr/mynewt_newtmgr.h
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_MYNEWT_NEWTMGR_
+#define H_MYNEWT_NEWTMGR_
+
+#include <inttypes.h>
+#include "mgmt/mgmt.h"
+#include "os/os_mbuf.h"
+struct mynewt_nmgr_transport;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Transmit function. The supplied mbuf is always consumed, regardless of
+ * return code.
+ */
+typedef int mynewt_nmgr_transport_out_fn(struct mynewt_nmgr_transport *mnt,
+ 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 mynewt_nmgr_transport_get_mtu_fn(struct os_mbuf *m);
+
+struct mynewt_nmgr_transport {
+ struct os_mqueue mnt_imq;
+ mynewt_nmgr_transport_out_fn *mnt_output;
+ mynewt_nmgr_transport_get_mtu_fn *mnt_get_mtu;
+};
+
+int mynewt_nmgr_transport_init(struct mynewt_nmgr_transport *mnt,
+ mynewt_nmgr_transport_out_fn *output_func,
+ mynewt_nmgr_transport_get_mtu_fn *get_mtu_func);
+
+int mynewt_nmgr_rx_req(struct mynewt_nmgr_transport *mnt, struct os_mbuf *req);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_MYNEWT_NETMGR_ */
diff --git a/newtmgr/port/mynewt/pkg.yml b/newtmgr/port/mynewt/pkg.yml
new file mode 100644
index 0000000..bb90250
--- /dev/null
+++ b/newtmgr/port/mynewt/pkg.yml
@@ -0,0 +1,30 @@
+#
+# 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/port/mynewt
+pkg.description: Server-side newtmgr functionality.
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+ - kernel/os
+ - mgmt/mgmt
+ - mgmt/mgmt_os
+ - util/mem
diff --git a/newtmgr/port/mynewt/src/mynewt_nmgr.c b/newtmgr/port/mynewt/src/mynewt_nmgr.c
new file mode 100644
index 0000000..7e90e7b
--- /dev/null
+++ b/newtmgr/port/mynewt/src/mynewt_nmgr.c
@@ -0,0 +1,273 @@
+#include "sysinit/sysinit.h"
+
+#include "os/os.h"
+#include "mynewt_mgmt/mynewt_mgmt.h"
+#include "newtmgr/newtmgr.h"
+#include "mgmt_os/mgmt_os.h"
+#include "mem/mem.h"
+#include "tinycbor/cbor_mbuf_reader.h"
+#include "tinycbor/cbor_mbuf_writer.h"
+#include "mynewt_newtmgr/mynewt_newtmgr.h"
+
+/* Shared queue that newtmgr uses for work items. */
+struct os_eventq *nmgr_evq;
+
+static mgmt_alloc_rsp_fn mynewt_nmgr_alloc_rsp;
+static mgmt_trim_front_fn mynewt_nmgr_trim_front;
+static mgmt_reset_buf_fn mynewt_nmgr_reset_buf;
+static mgmt_write_at_fn mynewt_nmgr_write_at;
+static mgmt_init_reader_fn mynewt_nmgr_init_reader;
+static mgmt_init_writer_fn mynewt_nmgr_init_writer;
+static mgmt_free_buf_fn mynewt_nmgr_free_buf;
+static nmgr_tx_rsp_fn mynewt_nmgr_tx_rsp;
+
+static const struct mgmt_streamer_cfg mynewt_nmgr_cbor_cfg = {
+ .alloc_rsp = mynewt_nmgr_alloc_rsp,
+ .trim_front = mynewt_nmgr_trim_front,
+ .reset_buf = mynewt_nmgr_reset_buf,
+ .write_at = mynewt_nmgr_write_at,
+ .init_reader = mynewt_nmgr_init_reader,
+ .init_writer = mynewt_nmgr_init_writer,
+ .free_buf = mynewt_nmgr_free_buf,
+};
+
+/**
+ * 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;
+}
+
+static void *
+mynewt_nmgr_alloc_rsp(const void *req, void *arg)
+{
+ const struct os_mbuf *om_req;
+ struct os_mbuf *om_rsp;
+
+ om_req = req;
+ om_rsp = os_msys_get_pkthdr(512, OS_MBUF_USRHDR_LEN(om_req));
+ if (om_rsp == NULL) {
+ return NULL;
+ }
+
+ /* Copy the request user header into the response. */
+ memcpy(OS_MBUF_USRHDR(om_rsp),
+ OS_MBUF_USRHDR(om_req),
+ OS_MBUF_USRHDR_LEN(om_req));
+
+ return om_rsp;
+}
+
+static int
+mynewt_nmgr_trim_front(void *buf, int len, void *arg)
+{
+ struct os_mbuf *om;
+
+ om = buf;
+ os_mbuf_adj(om, len);
+ return 0;
+}
+
+static void
+mynewt_nmgr_reset_buf(void *buf, void *arg)
+{
+ struct os_mbuf *om;
+
+ om = buf;
+ os_mbuf_adj(om, -OS_MBUF_PKTLEN(om));
+}
+
+static int
+mynewt_nmgr_write_at(struct cbor_encoder_writer *writer, int offset,
+ const void *data, int len, void *arg)
+{
+ struct cbor_mbuf_writer *mw;
+ int rc;
+
+ mw = (struct cbor_mbuf_writer *)writer;
+ rc = os_mbuf_copyinto(mw->m, offset, data, len);
+ if (rc != 0) {
+ return MGMT_ERR_EUNKNOWN;
+ }
+
+ return 0;
+}
+
+static int
+mynewt_nmgr_init_reader(struct cbor_decoder_reader *reader, void *buf,
+ void *arg)
+{
+ struct cbor_mbuf_reader *mr;
+
+ mr = (struct cbor_mbuf_reader *)reader;
+ cbor_mbuf_reader_init(mr, buf, 0);
+
+ return 0;
+}
+
+static int
+mynewt_nmgr_init_writer(struct cbor_encoder_writer *writer, void *buf,
+ void *arg)
+{
+ struct cbor_mbuf_writer *mw;
+
+ mw = (struct cbor_mbuf_writer *)writer;
+ cbor_mbuf_writer_init(mw, buf);
+
+ return 0;
+}
+
+static int
+mynewt_nmgr_tx_rsp(struct nmgr_streamer *ns, void *rsp, void *arg)
+{
+ struct mynewt_nmgr_transport *mnt;
+ struct os_mbuf *om_rsp;
+ struct os_mbuf *frag;
+ uint16_t mtu;
+ int rc;
+
+ mnt = arg;
+ om_rsp = rsp;
+
+ mtu = mnt->mnt_get_mtu(rsp);
+ if (mtu == 0) {
+ /* The transport cannot support a transmission right now. */
+ return MGMT_ERR_EUNKNOWN;
+ }
+
+ while (om_rsp != NULL) {
+ frag = mem_split_frag(&om_rsp, mtu, mynewt_nmgr_rsp_frag_alloc,
+ om_rsp);
+ if (frag == NULL) {
+ return MGMT_ERR_ENOMEM;
+ }
+
+ rc = mnt->mnt_output(mnt, frag);
+ if (rc != 0) {
+ /* Output function already freed mbuf. */
+ return MGMT_ERR_EUNKNOWN;
+ }
+ }
+
+ return MGMT_ERR_EOK;
+}
+
+static void
+mynewt_nmgr_free_buf(void *buf, void *arg)
+{
+ os_mbuf_free_chain(buf);
+}
+
+static void
+mynewt_nmgr_process(struct mynewt_nmgr_transport *mnt)
+{
+ struct cbor_mbuf_reader reader;
+ struct cbor_mbuf_writer writer;
+ struct nmgr_streamer streamer;
+ struct os_mbuf *req;
+ int rc;
+
+ streamer = (struct nmgr_streamer) {
+ .ns_base = {
+ .cfg = &mynewt_nmgr_cbor_cfg,
+ .reader = &reader.r,
+ .writer = &writer.enc,
+ .cb_arg = mnt,
+ },
+ .ns_tx_rsp = mynewt_nmgr_tx_rsp,
+ };
+
+ while (1) {
+ req = os_mqueue_get(&mnt->mnt_imq);
+ if (req == NULL) {
+ break;
+ }
+
+ rc = nmgr_process_single_packet(&streamer, 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,
+ mynewt_nmgr_transport_out_fn *output_func,
+ mynewt_nmgr_transport_get_mtu_fn *get_mtu_func)
+{
+ int rc;
+
+ *mnt = (struct mynewt_nmgr_transport) {
+ .mnt_output = output_func,
+ .mnt_get_mtu = get_mtu_func,
+ };
+
+ rc = os_mqueue_init(&mnt->mnt_imq, mynewt_nmgr_event_data_in, mnt);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+mynewt_nmgr_rx_req(struct mynewt_nmgr_transport *mnt, struct os_mbuf *req)
+{
+ int rc;
+
+ rc = os_mqueue_put(&mnt->mnt_imq, mgmt_evq_get(), req);
+ if (rc != 0) {
+ os_mbuf_free_chain(req);
+ }
+
+ return rc;
+}
+
+struct os_eventq *
+mgmt_evq_get(void)
+{
+ return nmgr_evq;
+}
+
+void
+mgmt_evq_set(struct os_eventq *evq)
+{
+ nmgr_evq = evq;
+}
+
+void
+nmgr_pkg_init(void)
+{
+ int rc;
+
+ /* Ensure this function only gets called by sysinit. */
+ SYSINIT_ASSERT_ACTIVE();
+
+ rc = mgmt_os_group_register();
+ SYSINIT_PANIC_ASSERT(rc == 0);
+
+ mgmt_evq_set(os_eventq_dflt_get());
+}
diff --git a/newtmgr/src/newtmgr.c b/newtmgr/src/newtmgr.c
new file mode 100644
index 0000000..5266cd7
--- /dev/null
+++ b/newtmgr/src/newtmgr.c
@@ -0,0 +1,353 @@
+/*
+ * 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 "mgmt/mgmt.h"
+#include "newtmgr/newtmgr.h"
+#include "tinycbor/cbor.h"
+#include "tinycbor/cbor_mbuf_writer.h"
+#include "tinycbor/cbor_mbuf_reader.h"
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+
+#ifndef ntohs
+#define ntohs(x) (x)
+#endif
+
+#ifndef htons
+#define htons(x) (x)
+#endif
+
+#else
+/* Little endian. */
+
+#ifndef ntohs
+#define ntohs(x) ((uint16_t) \
+ ((((x) & 0xff00) >> 8) | \
+ (((x) & 0x00ff) << 8)))
+#endif
+
+#ifndef htons
+#define htons(x) (ntohs(x))
+#endif
+
+#endif
+
+static int
+nmgr_align4(int x)
+{
+ int rem;
+
+ rem = x % 4;
+ if (rem == 0) {
+ return x;
+ } else {
+ return x - rem + 4;
+ }
+}
+
+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;
+ }
+}
+
+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 = (struct nmgr_hdr) {
+ .nh_len = 0,
+ .nh_flags = 0,
+ .nh_op = nmgr_rsp_op(req_hdr->nh_op),
+ .nh_group = req_hdr->nh_group,
+ .nh_seq = req_hdr->nh_seq,
+ .nh_id = req_hdr->nh_id,
+ };
+}
+
+static int
+nmgr_read_hdr(struct nmgr_streamer *streamer, struct nmgr_hdr *hdr)
+{
+ struct mgmt_streamer *base;
+
+ base = &streamer->ns_base;
+
+ if (base->reader->message_size < sizeof *hdr) {
+ return MGMT_ERR_EINVAL;
+ }
+
+ base->reader->cpy(base->reader, (char *)hdr, 0, sizeof *hdr);
+ return 0;
+}
+
+static int
+nmgr_write_hdr(struct nmgr_streamer *streamer, const struct nmgr_hdr *hdr)
+{
+ int rc;
+
+ rc = mgmt_streamer_write_at(&streamer->ns_base, 0, hdr, sizeof *hdr);
+ return mgmt_err_from_cbor(rc);
+}
+
+static int
+nmgr_build_err_rsp(struct nmgr_streamer *streamer,
+ 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, &streamer->ns_base);
+ if (rc != 0) {
+ return rc;
+ }
+
+ nmgr_init_rsp_hdr(req_hdr, &rsp_hdr);
+ rc = nmgr_write_hdr(streamer, &rsp_hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = cbor_encoder_create_map(&cbuf.encoder, &map, CborIndefiniteLength);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = mgmt_cbuf_setoerr(&cbuf, status);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = cbor_encoder_close_container(&cbuf.encoder, &map);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rsp_hdr.nh_len = htons(cbor_encode_bytes_written(&cbuf.encoder));
+ rc = nmgr_write_hdr(streamer, &rsp_hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+int
+nmgr_handle_single_payload(struct mgmt_cbuf *cbuf,
+ const struct nmgr_hdr *req_hdr)
+{
+ const struct mgmt_handler *handler;
+ struct CborEncoder payload_encoder;
+ int rc;
+
+ handler = mgmt_find_handler(req_hdr->nh_group, req_hdr->nh_id);
+ if (!handler) {
+ return MGMT_ERR_ENOENT;
+ }
+
+ /* 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;
+ }
+
+ return 0;
+}
+
+
+static int
+nmgr_handle_single_req(struct nmgr_streamer *streamer,
+ const struct nmgr_hdr *req_hdr)
+{
+ struct mgmt_cbuf cbuf;
+ struct nmgr_hdr rsp_hdr;
+ int rc;
+
+ rc = mgmt_cbuf_init(&cbuf, &streamer->ns_base);
+ if (rc != 0) {
+ return rc;
+ }
+
+ /* 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(streamer, &rsp_hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rc = nmgr_handle_single_payload(&cbuf, req_hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ rsp_hdr.nh_len = cbor_encode_bytes_written(&cbuf.encoder);
+ nmgr_hton_hdr(&rsp_hdr);
+ rc = nmgr_write_hdr(streamer, &rsp_hdr);
+ if (rc != 0) {
+ return rc;
+ }
+
+ return 0;
+}
+
+static void
+nmgr_on_err(struct nmgr_streamer *streamer,
+ const struct nmgr_hdr *req_hdr,
+ void *req,
+ void *rsp,
+ int status)
+{
+ int rc;
+
+ if (rsp == NULL) {
+ rsp = req;
+ req = NULL;
+ }
+
+ mgmt_streamer_reset_buf(&streamer->ns_base, rsp);
+ mgmt_streamer_init_writer(&streamer->ns_base, rsp);
+
+ rc = nmgr_build_err_rsp(streamer, req_hdr, status);
+ if (rc == 0) {
+ streamer->ns_tx_rsp(streamer, rsp, streamer->ns_base.cb_arg);
+ rsp = NULL;
+ }
+
+ mgmt_streamer_free_buf(&streamer->ns_base, req);
+ mgmt_streamer_free_buf(&streamer->ns_base, rsp);
+}
+
+int
+nmgr_process_single_packet(struct nmgr_streamer *streamer, void *req)
+{
+ struct nmgr_hdr req_hdr;
+ void *rsp;
+ bool valid_hdr;
+ int rc;
+
+ rsp = NULL;
+ valid_hdr = true;
+
+ while (1) {
+ rc = mgmt_streamer_init_reader(&streamer->ns_base, req);
+ if (rc != 0) {
+ valid_hdr = false;
+ break;
+ }
+
+ rc = nmgr_read_hdr(streamer, &req_hdr);
+ if (rc != 0) {
+ valid_hdr = false;
+ break;
+ }
+ nmgr_ntoh_hdr(&req_hdr);
+ rc = mgmt_streamer_trim_front(&streamer->ns_base, req, NMGR_HDR_SIZE);
+ assert(rc == 0);
+
+ rsp = mgmt_streamer_alloc_rsp(&streamer->ns_base, req);
+ if (rsp == NULL) {
+ rc = MGMT_ERR_ENOMEM;
+ break;
+ }
+
+ rc = mgmt_streamer_init_writer(&streamer->ns_base, rsp);
+ if (rc != 0) {
+ break;
+ }
+
+ rc = nmgr_handle_single_req(streamer, &req_hdr);
+ if (rc != 0) {
+ break;
+ }
+
+ rc = streamer->ns_tx_rsp(streamer, rsp, streamer->ns_base.cb_arg);
+ rsp = NULL;
+ if (rc != 0) {
+ break;
+ }
+
+ /* Trim processed request to free up space for subsequent responses. */
+ rc = mgmt_streamer_trim_front(&streamer->ns_base, req,
+ nmgr_align4(req_hdr.nh_len));
+ assert(rc == 0);
+ }
+
+ if (rc != 0 && valid_hdr) {
+ nmgr_on_err(streamer, &req_hdr, req, rsp, rc);
+ return rc;
+ }
+
+ mgmt_streamer_free_buf(&streamer->ns_base, req);
+ mgmt_streamer_free_buf(&streamer->ns_base, rsp);
+ return 0;
+}
--
To stop receiving notification emails like this one, please contact
['"commits@mynewt.apache.org" <co...@mynewt.apache.org>'].