From dc7a09ec4c58772f2564f0f5906b78444f4c78d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Narajowski?= Date: Mon, 25 May 2020 15:17:12 +0200 Subject: [PATCH] Add Memfault management command https://memfault.com/ Add support for commands to pull Memfault data from device such as coredump, events and traces. --- .../include/memfault_mgmt/memfault_mgmt.h | 36 ++++++ .../memfault_mgmt/memfault_mgmt_config.h | 41 ++++++ cmd/memfault_mgmt/pkg.yml | 31 +++++ cmd/memfault_mgmt/src/memfault_mgmt.c | 120 ++++++++++++++++++ cmd/memfault_mgmt/syscfg.yml | 24 ++++ mgmt/include/mgmt/mgmt.h | 1 + 6 files changed, 253 insertions(+) create mode 100644 cmd/memfault_mgmt/include/memfault_mgmt/memfault_mgmt.h create mode 100644 cmd/memfault_mgmt/include/memfault_mgmt/memfault_mgmt_config.h create mode 100644 cmd/memfault_mgmt/pkg.yml create mode 100644 cmd/memfault_mgmt/src/memfault_mgmt.c create mode 100644 cmd/memfault_mgmt/syscfg.yml diff --git a/cmd/memfault_mgmt/include/memfault_mgmt/memfault_mgmt.h b/cmd/memfault_mgmt/include/memfault_mgmt/memfault_mgmt.h new file mode 100644 index 00000000..4933987c --- /dev/null +++ b/cmd/memfault_mgmt/include/memfault_mgmt/memfault_mgmt.h @@ -0,0 +1,36 @@ +/* + * 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_MEMFAULT_MGMT_ +#define H_MEMFAULT_MGMT_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Command IDs for memfault management group. + */ +#define MEMFAULT_MGMT_ID_PULL 0 + +#ifdef __cplusplus +} +#endif + +#endif /* H_MEMFAULT_MGMT_ */ diff --git a/cmd/memfault_mgmt/include/memfault_mgmt/memfault_mgmt_config.h b/cmd/memfault_mgmt/include/memfault_mgmt/memfault_mgmt_config.h new file mode 100644 index 00000000..807e9036 --- /dev/null +++ b/cmd/memfault_mgmt/include/memfault_mgmt/memfault_mgmt_config.h @@ -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. + */ + +#ifndef H_MEMFAULT_MGMT_CONFIG_ +#define H_MEMFAULT_MGMT_CONFIG_ + +#if defined MYNEWT + +#include "syscfg/syscfg.h" + +#define MEMFAULT_MGMT_MAX_CHUNK_SIZE MYNEWT_VAL(MEMFAULT_MGMT_MAX_CHUNK_SIZE) + +#elif defined __ZEPHYR__ + +#define MEMFAULT_MGMT_MAX_CHUNK_SIZE CONFIG_MEMFAULT_MGMT_MAX_CHUNK_SIZE + +#else + +/* No direct support for this OS. The application needs to define the above + * settings itself. + */ + +#endif + +#endif diff --git a/cmd/memfault_mgmt/pkg.yml b/cmd/memfault_mgmt/pkg.yml new file mode 100644 index 00000000..7983cb3c --- /dev/null +++ b/cmd/memfault_mgmt/pkg.yml @@ -0,0 +1,31 @@ +# +# 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: cmd/memfault_mgmt +pkg.description: 'Memfault management command handlers for mcumgr.' +pkg.author: "Apache Mynewt " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + +pkg.deps: + - '@apache-mynewt-core/kernel/os' + - '@apache-mynewt-mcumgr/mgmt' + +pkg.init: + memfault_mgmt_module_init: 502 diff --git a/cmd/memfault_mgmt/src/memfault_mgmt.c b/cmd/memfault_mgmt/src/memfault_mgmt.c new file mode 100644 index 00000000..02d91a86 --- /dev/null +++ b/cmd/memfault_mgmt/src/memfault_mgmt.c @@ -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. + */ + +#include +#include + +#include "os/mynewt.h" +#include "mgmt/mgmt.h" +#include "cborattr/cborattr.h" +#include "memfault_mgmt/memfault_mgmt.h" +#include "memfault_mgmt/memfault_mgmt_config.h" +#include "memfault/core/data_packetizer.h" +#include "memfault/core/debug_log.h" + +static mgmt_handler_fn memfault_mgmt_pull; + +static struct mgmt_handler memfault_mgmt_handlers[] = { + [MEMFAULT_MGMT_ID_PULL] = { memfault_mgmt_pull, NULL }, +}; + +#define MEMFAULT_MGMT_HANDLER_CNT \ + (sizeof(memfault_mgmt_handlers) / sizeof(memfault_mgmt_handlers[0])) + +static struct mgmt_group memfault_mgmt_group = { + .mg_handlers = memfault_mgmt_handlers, + .mg_handlers_count = MEMFAULT_MGMT_HANDLER_CNT, + .mg_group_id = MGMT_GROUP_ID_MEMFAULT, +}; + + +static const sPacketizerConfig cfg = { + // Enable multi packet chunking. This means a chunk may span multiple calls to + // memfault_packetizer_get_next(). + .enable_multi_packet_chunk = true, +}; +static sPacketizerMetadata metadata; + +/** + * Command handler: memfault pull + */ +static int +memfault_mgmt_pull(struct mgmt_ctxt *ctxt) +{ + CborError err; + uint8_t buf[MEMFAULT_MGMT_MAX_CHUNK_SIZE]; + size_t buf_len = sizeof(buf); + + if (!metadata.send_in_progress) { + bool data_available = memfault_packetizer_begin(&cfg, &metadata); + if (!data_available) { + // there are no more chunks to send + MEMFAULT_LOG_INFO("All data has been sent!"); + return MGMT_ERR_EOK; + } + } + + eMemfaultPacketizerStatus packetizer_status = + memfault_packetizer_get_next(buf, &buf_len); + if (packetizer_status == kMemfaultPacketizerStatus_NoMoreData) { + MEMFAULT_LOG_ERROR("Unexpected packetizer status: %d", + (int)packetizer_status); + return MGMT_ERR_EBADSTATE; + } + + if (packetizer_status == kMemfaultPacketizerStatus_EndOfChunk) { + metadata.send_in_progress = false; + } + + struct cbor_attr_t attrs[] = { + { NULL }, + }; + + err = cbor_read_object(&ctxt->it, attrs); + if (err != 0) { + return MGMT_ERR_EINVAL; + } + + err |= cbor_encode_text_stringz(&ctxt->encoder, "rc"); + err |= cbor_encode_int(&ctxt->encoder, MGMT_ERR_EOK); + err |= cbor_encode_text_stringz(&ctxt->encoder, "status"); + err |= cbor_encode_int(&ctxt->encoder, packetizer_status); + err |= cbor_encode_text_stringz(&ctxt->encoder, "data"); + err |= cbor_encode_byte_string(&ctxt->encoder, buf, buf_len); + if (err != 0) { + return MGMT_ERR_ENOMEM; + } + + return MGMT_ERR_EOK; +} + +void +memfault_mgmt_register_group(void) +{ + mgmt_register_group(&memfault_mgmt_group); +} + +void +memfault_mgmt_module_init(void) +{ + /* Ensure this function only gets called by sysinit. */ + SYSINIT_ASSERT_ACTIVE(); + + memfault_mgmt_register_group(); +} diff --git a/cmd/memfault_mgmt/syscfg.yml b/cmd/memfault_mgmt/syscfg.yml new file mode 100644 index 00000000..71d6a97c --- /dev/null +++ b/cmd/memfault_mgmt/syscfg.yml @@ -0,0 +1,24 @@ +# 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: + MEMFAULT_MGMT_MAX_CHUNK_SIZE: + description: > + The maximum amount of core data that can fit in a single NMP message + value: 512 + diff --git a/mgmt/include/mgmt/mgmt.h b/mgmt/include/mgmt/mgmt.h index 7ad22dfa..1f093c77 100644 --- a/mgmt/include/mgmt/mgmt.h +++ b/mgmt/include/mgmt/mgmt.h @@ -50,6 +50,7 @@ extern "C" { #define MGMT_GROUP_ID_RUN 7 #define MGMT_GROUP_ID_FS 8 #define MGMT_GROUP_ID_SHELL 9 +#define MGMT_GROUP_ID_MEMFAULT 10 #define MGMT_GROUP_ID_PERUSER 64 /**