You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2017/05/17 17:14:45 UTC
[5/8] incubator-mynewt-core git commit: sys/shell: add support for
newtmgr over shell
sys/shell: add support for newtmgr over shell
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/44504b96
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/44504b96
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/44504b96
Branch: refs/heads/master
Commit: 44504b96f941907fd23dd56eeab8453859373245
Parents: 038dc7f
Author: Michał Narajowski <mi...@codecoup.pl>
Authored: Wed May 3 10:48:54 2017 +0200
Committer: Michał Narajowski <mi...@codecoup.pl>
Committed: Wed May 3 12:12:41 2017 +0200
----------------------------------------------------------------------
sys/shell/include/shell/shell.h | 7 +
sys/shell/pkg.yml | 2 +
sys/shell/src/shell.c | 32 +++++
sys/shell/src/shell_nlip.c | 252 +++++++++++++++++++++++++++++++++++
sys/shell/src/shell_priv.h | 11 ++
sys/shell/syscfg.yml | 3 +
6 files changed, 307 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/44504b96/sys/shell/include/shell/shell.h
----------------------------------------------------------------------
diff --git a/sys/shell/include/shell/shell.h b/sys/shell/include/shell/shell.h
index fdb263a..38cb606 100644
--- a/sys/shell/include/shell/shell.h
+++ b/sys/shell/include/shell/shell.h
@@ -101,6 +101,13 @@ void shell_register_prompt_handler(shell_prompt_function_t handler);
*/
void shell_register_default_module(const char *name);
+#if MYNEWT_VAL(SHELL_NEWTMGR)
+struct os_mbuf;
+typedef int (*shell_nlip_input_func_t)(struct os_mbuf *, void *arg);
+int shell_nlip_input_register(shell_nlip_input_func_t nf, void *arg);
+int shell_nlip_output(struct os_mbuf *m);
+#endif
+
#if MYNEWT_VAL(SHELL_COMPAT)
int shell_cmd_register(struct shell_cmd *sc);
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/44504b96/sys/shell/pkg.yml
----------------------------------------------------------------------
diff --git a/sys/shell/pkg.yml b/sys/shell/pkg.yml
index 1f38a8d..71d88a5 100644
--- a/sys/shell/pkg.yml
+++ b/sys/shell/pkg.yml
@@ -26,6 +26,8 @@ pkg.keywords:
pkg.deps:
- kernel/os
- time/datetime
+ - encoding/base64
+ - util/crc
pkg.req_apis:
- console
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/44504b96/sys/shell/src/shell.c
----------------------------------------------------------------------
diff --git a/sys/shell/src/shell.c b/sys/shell/src/shell.c
index d186aa7..959a0a3 100644
--- a/sys/shell/src/shell.c
+++ b/sys/shell/src/shell.c
@@ -381,6 +381,30 @@ shell_process_command(char *line)
console_printf("%s", get_prompt());
}
+#if MYNEWT_VAL(SHELL_NEWTMGR)
+static void
+shell_process_nlip_line(char *shell_line)
+{
+ size_t shell_line_len;
+
+ shell_line_len = strlen(shell_line);
+ if (shell_line_len > 2) {
+ if (shell_line[0] == SHELL_NLIP_PKT_START1 &&
+ shell_line[1] == SHELL_NLIP_PKT_START2) {
+ shell_nlip_clear_pkt();
+ shell_nlip_process(&shell_line[2], shell_line_len - 2);
+ } else if (shell_line[0] == SHELL_NLIP_DATA_START1 &&
+ shell_line[1] == SHELL_NLIP_DATA_START2) {
+ shell_nlip_process(&shell_line[2], shell_line_len - 2);
+ } else {
+ shell_process_command(shell_line);
+ }
+ } else {
+ shell_process_command(shell_line);
+ }
+}
+#endif
+
static void
shell(struct os_event *ev)
{
@@ -397,7 +421,11 @@ shell(struct os_event *ev)
return;
}
+#if MYNEWT_VAL(SHELL_NEWTMGR)
+ shell_process_nlip_line(cmd->line);
+#else
shell_process_command(cmd->line);
+#endif
os_eventq_put(&avail_queue, ev);
}
@@ -893,6 +921,10 @@ shell_init(void)
prompt = SHELL_PROMPT;
console_set_queues(&avail_queue, os_eventq_dflt_get());
+#if MYNEWT_VAL(SHELL_NEWTMGR)
+ shell_nlip_init();
+#endif
+
#if MYNEWT_VAL(SHELL_COMPLETION)
console_set_completion_cb(completion);
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/44504b96/sys/shell/src/shell_nlip.c
----------------------------------------------------------------------
diff --git a/sys/shell/src/shell_nlip.c b/sys/shell/src/shell_nlip.c
new file mode 100644
index 0000000..e967cd2
--- /dev/null
+++ b/sys/shell/src/shell_nlip.c
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(SHELL_NEWTMGR)
+#include <stddef.h>
+#include "os/os.h"
+#include "os/endian.h"
+#include "base64/base64.h"
+#include "crc/crc16.h"
+#include "console/console.h"
+#include "shell/shell.h"
+#include "shell_priv.h"
+
+static shell_nlip_input_func_t g_shell_nlip_in_func;
+static void *g_shell_nlip_in_arg;
+static struct os_mqueue g_shell_nlip_mq;
+static struct os_mbuf *g_nlip_mbuf;
+static uint16_t g_nlip_expected_len;
+
+void
+shell_nlip_clear_pkt(void)
+{
+ if (g_nlip_mbuf) {
+ os_mbuf_free_chain(g_nlip_mbuf);
+ g_nlip_mbuf = NULL;
+ }
+ g_nlip_expected_len = 0;
+}
+
+int
+shell_nlip_process(char *data, int len)
+{
+ uint16_t copy_len;
+ int rc;
+ struct os_mbuf *m;
+ uint16_t crc;
+
+ rc = base64_decode(data, data);
+ if (rc < 0) {
+ goto err;
+ }
+ len = rc;
+
+ if (g_nlip_mbuf == NULL) {
+ if (len < 2) {
+ rc = -1;
+ goto err;
+ }
+
+ g_nlip_expected_len = ntohs(*(uint16_t *) data);
+ g_nlip_mbuf = os_msys_get_pkthdr(g_nlip_expected_len, 0);
+ if (!g_nlip_mbuf) {
+ rc = -1;
+ goto err;
+ }
+
+ data += sizeof(uint16_t);
+ len -= sizeof(uint16_t);
+ }
+
+ copy_len = min(g_nlip_expected_len - OS_MBUF_PKTHDR(g_nlip_mbuf)->omp_len,
+ len);
+
+ rc = os_mbuf_copyinto(g_nlip_mbuf, OS_MBUF_PKTHDR(g_nlip_mbuf)->omp_len,
+ data, copy_len);
+ if (rc != 0) {
+ goto err;
+ }
+
+ if (OS_MBUF_PKTHDR(g_nlip_mbuf)->omp_len == g_nlip_expected_len) {
+ if (g_shell_nlip_in_func) {
+ crc = CRC16_INITIAL_CRC;
+ for (m = g_nlip_mbuf; m; m = SLIST_NEXT(m, om_next)) {
+ crc = crc16_ccitt(crc, m->om_data, m->om_len);
+ }
+ if (crc == 0 && g_nlip_expected_len >= sizeof(crc)) {
+ os_mbuf_adj(g_nlip_mbuf, -sizeof(crc));
+ g_shell_nlip_in_func(g_nlip_mbuf, g_shell_nlip_in_arg);
+ } else {
+ os_mbuf_free_chain(g_nlip_mbuf);
+ }
+ } else {
+ os_mbuf_free_chain(g_nlip_mbuf);
+ }
+ g_nlip_mbuf = NULL;
+ g_nlip_expected_len = 0;
+ }
+
+ return (0);
+err:
+ return (rc);
+}
+
+static int
+shell_nlip_mtx(struct os_mbuf *m)
+{
+#define SHELL_NLIP_MTX_BUF_SIZE (12)
+ uint8_t readbuf[SHELL_NLIP_MTX_BUF_SIZE];
+ char encodebuf[BASE64_ENCODE_SIZE(SHELL_NLIP_MTX_BUF_SIZE)];
+ char pkt_seq[3] = { '\n', SHELL_NLIP_PKT_START1, SHELL_NLIP_PKT_START2 };
+ char esc_seq[2] = { SHELL_NLIP_DATA_START1, SHELL_NLIP_DATA_START2 };
+ uint16_t totlen;
+ uint16_t dlen;
+ uint16_t off;
+ uint16_t crc;
+ int rb_off;
+ int elen;
+ uint16_t nwritten;
+ uint16_t linelen;
+ int rc;
+ struct os_mbuf *tmp;
+ void *ptr;
+
+ /* Convert the mbuf into a packet.
+ *
+ * starts with 06 09
+ * base64 encode:
+ * - total packet length (uint16_t)
+ * - data
+ * - crc
+ * base64 encoded data must be less than 122 bytes per line to
+ * avoid overflows and adhere to convention.
+ *
+ * continuation packets are preceded by 04 20 until the entire
+ * buffer has been sent.
+ */
+ crc = CRC16_INITIAL_CRC;
+ for (tmp = m; tmp; tmp = SLIST_NEXT(tmp, om_next)) {
+ crc = crc16_ccitt(crc, tmp->om_data, tmp->om_len);
+ }
+ crc = htons(crc);
+ ptr = os_mbuf_extend(m, sizeof(crc));
+ if (!ptr) {
+ rc = -1;
+ goto err;
+ }
+ memcpy(ptr, &crc, sizeof(crc));
+
+ totlen = OS_MBUF_PKTHDR(m)->omp_len;
+ nwritten = 0;
+ off = 0;
+
+ /* Start a packet */
+ console_write(pkt_seq, sizeof(pkt_seq));
+
+ linelen = 0;
+
+ rb_off = 2;
+ dlen = htons(totlen);
+ memcpy(readbuf, &dlen, sizeof(dlen));
+
+ while (totlen > 0) {
+ dlen = min(SHELL_NLIP_MTX_BUF_SIZE - rb_off, totlen);
+
+ rc = os_mbuf_copydata(m, off, dlen, readbuf + rb_off);
+ if (rc != 0) {
+ goto err;
+ }
+ off += dlen;
+
+ /* If the next packet will overwhelm the line length, truncate
+ * this line.
+ */
+ if (linelen +
+ BASE64_ENCODE_SIZE(min(SHELL_NLIP_MTX_BUF_SIZE - rb_off,
+ totlen - dlen)) >= 120) {
+ elen = base64_encode(readbuf, dlen + rb_off, encodebuf, 1);
+ console_write(encodebuf, elen);
+ console_write("\n", 1);
+ console_write(esc_seq, sizeof(esc_seq));
+ linelen = 0;
+ } else {
+ elen = base64_encode(readbuf, dlen + rb_off, encodebuf, 0);
+ console_write(encodebuf, elen);
+ linelen += elen;
+ }
+
+ rb_off = 0;
+
+ nwritten += elen;
+ totlen -= dlen;
+ }
+
+ elen = base64_pad(encodebuf, linelen);
+ console_write(encodebuf, elen);
+
+ console_write("\n", 1);
+
+ return (0);
+err:
+ return (rc);
+}
+
+int
+shell_nlip_input_register(shell_nlip_input_func_t nf, void *arg)
+{
+ g_shell_nlip_in_func = nf;
+ g_shell_nlip_in_arg = arg;
+
+ return (0);
+}
+
+int
+shell_nlip_output(struct os_mbuf *m)
+{
+ return os_mqueue_put(&g_shell_nlip_mq, os_eventq_dflt_get(), m);
+}
+
+static void
+shell_event_data_in(struct os_event *ev)
+{
+ struct os_mbuf *m;
+
+ /* Copy data out of the mbuf 12 bytes at a time and write it to
+ * the console.
+ */
+ while (1) {
+ m = os_mqueue_get(&g_shell_nlip_mq);
+ if (!m) {
+ break;
+ }
+
+ (void) shell_nlip_mtx(m);
+
+ os_mbuf_free_chain(m);
+ }
+}
+
+void
+shell_nlip_init(void)
+{
+ os_mqueue_init(&g_shell_nlip_mq, shell_event_data_in, NULL);
+}
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/44504b96/sys/shell/src/shell_priv.h
----------------------------------------------------------------------
diff --git a/sys/shell/src/shell_priv.h b/sys/shell/src/shell_priv.h
index fbb44c2..2efa2cd 100644
--- a/sys/shell/src/shell_priv.h
+++ b/sys/shell/src/shell_priv.h
@@ -26,6 +26,17 @@ extern "C" {
#include "shell/shell.h"
+#if MYNEWT_VAL(SHELL_NEWTMGR)
+#define SHELL_NLIP_PKT_START1 (6)
+#define SHELL_NLIP_PKT_START2 (9)
+#define SHELL_NLIP_DATA_START1 (4)
+#define SHELL_NLIP_DATA_START2 (20)
+
+int shell_nlip_process(char *data, int len);
+void shell_nlip_init(void);
+void shell_nlip_clear_pkt(void);
+#endif
+
void shell_os_register(shell_register_function_t register_func);
void shell_prompt_register(shell_register_function_t register_func);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/44504b96/sys/shell/syscfg.yml
----------------------------------------------------------------------
diff --git a/sys/shell/syscfg.yml b/sys/shell/syscfg.yml
index e4d78f8..72b686d 100644
--- a/sys/shell/syscfg.yml
+++ b/sys/shell/syscfg.yml
@@ -44,6 +44,9 @@ syscfg.defs:
SHELL_COMPLETION:
description: 'Include completion functionality'
value: 1
+ SHELL_NEWTMGR:
+ description: 'Enable newtmgr over shell'
+ value: 1
SHELL_OS_MODULE:
description: 'Include shell os module'