From e51ec54c02bc77578cf52f345724c2ce41cc5e8d Mon Sep 17 00:00:00 2001 From: chao an Date: Thu, 18 May 2023 11:19:27 +0800 Subject: [PATCH] stream/hexdump: add hexdump stream to dump binary to syslog Signed-off-by: chao an --- include/nuttx/streams.h | 27 ++++ libs/libc/stream/Kconfig | 4 + libs/libc/stream/Make.defs | 1 + libs/libc/stream/lib_hexdumpstream.c | 182 +++++++++++++++++++++++++++ 4 files changed, 214 insertions(+) create mode 100644 libs/libc/stream/lib_hexdumpstream.c diff --git a/include/nuttx/streams.h b/include/nuttx/streams.h index 0e74d9bdb2f..e23b6024761 100644 --- a/include/nuttx/streams.h +++ b/include/nuttx/streams.h @@ -225,6 +225,14 @@ struct lib_bufferedoutstream_s char buffer[CONFIG_STREAM_OUT_BUFFER_SIZE]; }; +struct lib_hexdumpstream_s +{ + struct lib_outstream_s public; + FAR struct lib_outstream_s *backend; + int pending; + char buffer[CONFIG_STREAM_HEXDUMP_BUFFER_SIZE + 1]; +}; + /* This is a special stream that does buffered character I/O. NOTE that is * CONFIG_SYSLOG_BUFFER is not defined, it is the same as struct * lib_outstream_s @@ -413,6 +421,25 @@ void lib_rawsostream(FAR struct lib_rawsostream_s *outstream, int fd); void lib_bufferedoutstream(FAR struct lib_bufferedoutstream_s *outstream, FAR struct lib_outstream_s *backend); +/**************************************************************************** + * Name: lib_hexdumpstream + * + * Description: + * Convert binary stream to hex and redirect to syslog + * + * Input Parameters: + * stream - User allocated, uninitialized instance of struct + * lib_bufferedoutstream_s to be initialized. + * backend - Stream backend port. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_hexdumpstream(FAR struct lib_hexdumpstream_s *stream, + FAR struct lib_outstream_s *backend); + /**************************************************************************** * Name: lib_lowoutstream * diff --git a/libs/libc/stream/Kconfig b/libs/libc/stream/Kconfig index 77cb42e3dab..ebf32b5a1ca 100644 --- a/libs/libc/stream/Kconfig +++ b/libs/libc/stream/Kconfig @@ -25,4 +25,8 @@ config STREAM_OUT_BUFFER_SIZE int "Output stream buffer size" default 64 +config STREAM_HEXDUMP_BUFFER_SIZE + int "Output hexdump stream buffer size" + default 128 + endmenu # Locale Support diff --git a/libs/libc/stream/Make.defs b/libs/libc/stream/Make.defs index 055a4f7063d..2be97e9b196 100644 --- a/libs/libc/stream/Make.defs +++ b/libs/libc/stream/Make.defs @@ -27,6 +27,7 @@ CSRCS += lib_rawoutstream.c lib_rawsistream.c lib_rawsostream.c CSRCS += lib_zeroinstream.c lib_nullinstream.c lib_nulloutstream.c CSRCS += lib_mtdoutstream.c lib_libnoflush.c lib_libsnoflush.c CSRCS += lib_syslogstream.c lib_syslograwstream.c lib_bufferedoutstream.c +CSRCS += lib_hexdumpstream.c # The remaining sources files depend upon C streams diff --git a/libs/libc/stream/lib_hexdumpstream.c b/libs/libc/stream/lib_hexdumpstream.c new file mode 100644 index 00000000000..9679638a469 --- /dev/null +++ b/libs/libc/stream/lib_hexdumpstream.c @@ -0,0 +1,182 @@ +/**************************************************************************** + * libs/libc/stream/lib_hexdumpstream.c + * + * 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: nibble2hex + * + * Description: + * Convert a binary nibble to a hexadecimal character. + * + ****************************************************************************/ + +static char nibble2hex(unsigned char nibble) +{ + if (nibble < 10) + { + return '0' + nibble; + } + else + { + return 'A' + nibble - 10; + } +} + +/**************************************************************************** + * Name: bin2hex + ****************************************************************************/ + +static size_t bin2hex(FAR const uint8_t *buf, size_t buflen, + FAR char *hex, size_t hexlen) +{ + size_t i; + + if (buflen > hexlen) + { + buflen = hexlen; + } + + for (i = 0; i < buflen; i++) + { + hex[2 * i] = nibble2hex(buf[i] >> 4); + hex[2 * i + 1] = nibble2hex(buf[i] & 0xf); + } + + return buflen; +} + +/**************************************************************************** + * Name: hexdumpstream_flush + ****************************************************************************/ + +static int hexdumpstream_flush(FAR struct lib_outstream_s *this) +{ + FAR struct lib_hexdumpstream_s *rthis = (FAR void *)this; + + if (rthis->pending > 0) + { + rthis->buffer[rthis->pending] = '\n'; + lib_stream_puts(rthis->backend, rthis->buffer, rthis->pending + 1); + rthis->pending = 0; + } + + return OK; +} + +/**************************************************************************** + * Name: hexdumpstream_putc + ****************************************************************************/ + +static void hexdumpstream_putc(FAR struct lib_outstream_s *this, int ch) +{ + FAR struct lib_hexdumpstream_s *rthis = (FAR void *)this; + int outlen = CONFIG_STREAM_HEXDUMP_BUFFER_SIZE; + const uint8_t byte = ch; + + bin2hex(&byte, 1, rthis->buffer + rthis->pending, + (outlen - rthis->pending) / 2); + + rthis->pending += 2; + + if (rthis->pending == outlen) + { + hexdumpstream_flush(this); + } +} + +/**************************************************************************** + * Name: hexdumpstream_puts + ****************************************************************************/ + +static int hexdumpstream_puts(FAR struct lib_outstream_s *this, + FAR const void *buf, int len) +{ + FAR struct lib_hexdumpstream_s *rthis = (FAR void *)this; + const unsigned char *p = buf; + int outlen = CONFIG_STREAM_HEXDUMP_BUFFER_SIZE; + int line = outlen / 2; + int remain = len; + int ret; + + while (remain > 0) + { + ret = remain > line ? line : remain; + ret = bin2hex(p, ret, rthis->buffer + rthis->pending, + (outlen - rthis->pending) / 2); + + p += ret; + remain -= ret; + rthis->pending += ret * 2; + + if (rthis->pending == outlen) + { + hexdumpstream_flush(this); + } + } + + this->nput += len; + + return len; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_hexdumpstream + * + * Description: + * Convert binary stream to hex and redirect to syslog + * + * Input Parameters: + * stream - User allocated, uninitialized instance of struct + * lib_bufferedoutstream_s to be initialized. + * backend - Stream backend port. + * + * Returned Value: + * None (User allocated instance initialized). + * + ****************************************************************************/ + +void lib_hexdumpstream(FAR struct lib_hexdumpstream_s *stream, + FAR struct lib_outstream_s *backend) +{ + struct lib_outstream_s *public = &stream->public; + + public->putc = hexdumpstream_putc; + public->puts = hexdumpstream_puts; + public->flush = hexdumpstream_flush; + public->nput = 0; + + stream->pending = 0; + stream->backend = backend; +}