This is an automated email from the ASF dual-hosted git repository. jerzy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
The following commit(s) were added to refs/heads/master by this push: new 5653927 sys/console: Add TCP console 5653927 is described below commit 5653927da2c24546049d5e116af9125ebc90cda2 Author: Jerzy Kasenberg <je...@apache.org> AuthorDate: Wed Mar 31 19:48:37 2021 +0200 sys/console: Add TCP console This adds TCP console implementation. --- sys/console/full/pkg.yml | 2 + sys/console/full/src/console.c | 3 + sys/console/full/src/console_priv.h | 1 + sys/console/full/syscfg.yml | 3 + sys/console/full/{ => tcp_console}/pkg.yml | 25 +-- sys/console/full/tcp_console/src/tcp_console.c | 201 +++++++++++++++++++++++++ sys/console/full/tcp_console/syscfg.yml | 23 +++ 7 files changed, 240 insertions(+), 18 deletions(-) diff --git a/sys/console/full/pkg.yml b/sys/console/full/pkg.yml index cda20d9..c0d44f3 100644 --- a/sys/console/full/pkg.yml +++ b/sys/console/full/pkg.yml @@ -34,6 +34,8 @@ pkg.deps.CONSOLE_SEMIHOSTING: - "@apache-mynewt-core/hw/drivers/semihosting" pkg.deps.CONSOLE_USB: - "@apache-mynewt-core/hw/usb/tinyusb/cdc_console" +pkg.deps.CONSOLE_TCP: + - "@apache-mynewt-core/sys/console/full/tcp_console" pkg.deps.'CONSOLE_HISTORY == "ram"': - "@apache-mynewt-core/sys/console/full/history_ram" pkg.deps.'CONSOLE_HISTORY == "log"': diff --git a/sys/console/full/src/console.c b/sys/console/full/src/console.c index b271c08..346941c 100644 --- a/sys/console/full/src/console.c +++ b/sys/console/full/src/console.c @@ -1251,6 +1251,9 @@ console_is_init(void) #if MYNEWT_VAL(CONSOLE_USB) return usb_cdc_console_is_init(); #endif +#if MYNEWT_VAL(CONSOLE_TCP) + return tcp_console_is_init(); +#endif return 0; } diff --git a/sys/console/full/src/console_priv.h b/sys/console/full/src/console_priv.h index abcef5f..cf6be3a 100644 --- a/sys/console/full/src/console_priv.h +++ b/sys/console/full/src/console_priv.h @@ -34,6 +34,7 @@ int rtt_console_init(void); int semihosting_console_is_init(void); int ble_monitor_console_is_init(void); int usb_cdc_console_is_init(void); +int tcp_console_is_init(void); #ifdef __cplusplus } diff --git a/sys/console/full/syscfg.yml b/sys/console/full/syscfg.yml index ee81710..756d5cc 100644 --- a/sys/console/full/syscfg.yml +++ b/sys/console/full/syscfg.yml @@ -29,6 +29,9 @@ syscfg.defs: CONSOLE_USB: description: 'Set console to USB' value: 0 + CONSOLE_TCP: + description: 'Set console to TCP socket' + value: 0 CONSOLE_BLE_MONITOR: description: 'Set console output to BLE Monitor' value: 0 diff --git a/sys/console/full/pkg.yml b/sys/console/full/tcp_console/pkg.yml similarity index 57% copy from sys/console/full/pkg.yml copy to sys/console/full/tcp_console/pkg.yml index cda20d9..60fc9c7 100644 --- a/sys/console/full/pkg.yml +++ b/sys/console/full/tcp_console/pkg.yml @@ -6,7 +6,7 @@ # 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, @@ -17,28 +17,17 @@ # under the License. # -pkg.name: sys/console/full -pkg.description: Text-based IO interface. +pkg.name: sys/console/full/tcp_console +pkg.description: Console over TCP LWIP socket. pkg.author: "Apache Mynewt <d...@mynewt.apache.org>" pkg.homepage: "http://mynewt.apache.org/" pkg.keywords: pkg.deps: - - "@apache-mynewt-core/hw/hal" - - "@apache-mynewt-core/kernel/os" -pkg.deps.CONSOLE_UART: - - "@apache-mynewt-core/hw/drivers/uart" -pkg.deps.CONSOLE_RTT: - - "@apache-mynewt-core/hw/drivers/rtt" -pkg.deps.CONSOLE_SEMIHOSTING: - - "@apache-mynewt-core/hw/drivers/semihosting" -pkg.deps.CONSOLE_USB: - - "@apache-mynewt-core/hw/usb/tinyusb/cdc_console" -pkg.deps.'CONSOLE_HISTORY == "ram"': - - "@apache-mynewt-core/sys/console/full/history_ram" -pkg.deps.'CONSOLE_HISTORY == "log"': - - "@apache-mynewt-core/sys/console/full/history_log" + - "@apache-mynewt-core/sys/console/full" + - "@apache-mynewt-core/net/ip/mn_socket" + pkg.apis: console pkg.init: - console_pkg_init: 'MYNEWT_VAL(CONSOLE_SYSINIT_STAGE)' + tcp_console_pkg_init: 'MYNEWT_VAL(IP_SYSINIT_STAGE)' diff --git a/sys/console/full/tcp_console/src/tcp_console.c b/sys/console/full/tcp_console/src/tcp_console.c new file mode 100644 index 0000000..f2b4fad --- /dev/null +++ b/sys/console/full/tcp_console/src/tcp_console.c @@ -0,0 +1,201 @@ +/* + * 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/mynewt.h> + +#include <console/console.h> +#include <mn_socket/mn_socket.h> + +static struct os_event rx_receive_event; +static struct os_event tx_flush_event; +struct os_mbuf *tcp_console_out_buf; + +static struct mn_socket *server_socket; +static struct mn_socket *console_socket; + +static void +tcp_console_flush(void) +{ + int rc; + + if (tcp_console_out_buf != NULL && console_socket != NULL) { + rc = mn_sendto(console_socket, tcp_console_out_buf, NULL); + /* If data was sent, forget about buffer, otherwise keep buffer + * and add more data into it */ + if (rc == 0) { + tcp_console_out_buf = NULL; + } + } +} + +static void +tcp_console_schedule_tx_flush(void) +{ + os_eventq_put(os_eventq_dflt_get(), &tx_flush_event); +} + +static void +tcp_console_write(int c) +{ + uint8_t buf[1] = { (uint8_t)c }; + + /* If current mbuf was full, try to send it to client */ + if (tcp_console_out_buf != NULL && OS_MBUF_TRAILINGSPACE(tcp_console_out_buf) == 0) { + tcp_console_flush(); + /* + * This may not succeed it socket is not writable yet, mbuf will be still present + * and additional data will be appended. + */ + } + if (tcp_console_out_buf == NULL) { + tcp_console_out_buf = os_msys_get_pkthdr(0, 0); + } + + os_mbuf_append(tcp_console_out_buf, buf, 1); + + /* If mbuf was just filled up try to send it to client. */ + if (OS_MBUF_TRAILINGSPACE(tcp_console_out_buf) == 0) { + tcp_console_flush(); + } +} + +int +console_out_nolock(int c) +{ + tcp_console_write(c); + + if ('\n' == c) { + tcp_console_write('\r'); + } + + /* + * Scheduling flush means that event will be process just after everything + * else is done. Usually it means that data will be flushed after full + * console_printf(). + */ + tcp_console_schedule_tx_flush(); + + return c; +} + +void +console_rx_restart(void) +{ + os_eventq_put(os_eventq_dflt_get(), &rx_receive_event); +} + +static void +tx_flush_ev_cb(struct os_event *ev) +{ + tcp_console_flush(); +} + +static void +rx_ev_cb(struct os_event *ev) +{ + /* TODO: Check if this really needed */ +} + +static void +tcp_console_readable(void *arg, int err) +{ + struct os_mbuf *m; + int rc; + (void)rc; + + if (err == MN_ECONNABORTED) { + if (console_socket) { + mn_close(console_socket); + console_socket = NULL; + } + } else if (err == 0) { + assert(console_socket != NULL); + rc = mn_recvfrom(console_socket, &m, NULL); + assert(rc == 0); + for (int i = 0; i < m->om_len; ++i) { + console_handle_char(m->om_data[i]); + } + os_mbuf_free_chain(m); + } +} + +static void +tcp_console_writable(void *arg, int err) +{ + if (err == 0) { + tcp_console_flush(); + } +} + +static const union mn_socket_cb tcp_console_cbs = { + .socket.readable = tcp_console_readable, + .socket.writable = tcp_console_writable, +}; + +static int +tcp_console_newconn(void *arg, struct mn_socket *new) +{ + mn_socket_set_cbs(new, NULL, &tcp_console_cbs); + if (console_socket != NULL) { + mn_close(console_socket); + } + console_socket = new; + return 0; +} + +static const union mn_socket_cb server_listen_cbs = { + .listen.newconn = tcp_console_newconn, +}; + +int +tcp_console_pkg_init(void) +{ + struct mn_sockaddr_in sin = {0}; + int rc; + + rx_receive_event.ev_cb = rx_ev_cb; + tx_flush_event.ev_cb = tx_flush_ev_cb; + + /* Create normal TCP socket */ + rc = mn_socket(&server_socket, MN_PF_INET, MN_SOCK_STREAM, 0); + assert(rc == 0); + + sin.msin_len = sizeof(sin); + sin.msin_family = MN_AF_INET; + sin.msin_port = htons(MYNEWT_VAL(TCP_CONSOLE_PORT)); + + /* Bind it to all interfaces */ + rc = mn_bind(server_socket, (struct mn_sockaddr *)&sin); + assert(rc == 0); + + mn_socket_set_cbs(server_socket, NULL, &server_listen_cbs); + + /* Get ready for incoming connections */ + rc = mn_listen(server_socket, 2); + assert(rc == 0); + + return 0; +} + +int +tcp_console_is_init(void) +{ + /* TODO: Console check what should be returned */ + return 1; +} diff --git a/sys/console/full/tcp_console/syscfg.yml b/sys/console/full/tcp_console/syscfg.yml new file mode 100644 index 0000000..07773c2 --- /dev/null +++ b/sys/console/full/tcp_console/syscfg.yml @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +syscfg.defs: + TCP_CONSOLE_PORT: + description: 'Set console TCP port' + value: 4444 + restriction: $notnull