summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrederic Berat <fberat@de.adit-jv.com>2015-10-07 19:35:25 +0900
committerLutz Helwing <lutz_helwing@mentor.com>2015-11-24 09:48:42 +0100
commit5574d46a4083d783a915688e0e05593b9558497b (patch)
tree27284c79587b1576703424fb68d71e09d552b259
parent8ed28dc15429a736c8404d491ed73fd0b04235e2 (diff)
downloadDLT-daemon-5574d46a4083d783a915688e0e05593b9558497b.tar.gz
Control application: Control appliction to support offline log storage trigger
Features : 1. One shot trigger with path 2. Automounter based trigger 3. Udev based trigger Signed-off-by: Frederic Berat <fberat@de.adit-jv.com> Signed-off-by: Christoph Lipka <clipka@jp.adit-jv.com> Signed-off-by: anitha.ba <anithaammaji.baggam@in.bosch.com> Signed-off-by: S. Hameed <shameed@jp.adit-jv.com>
-rw-r--r--CMakeLists.txt13
-rw-r--r--src/console/CMakeLists.txt3
-rw-r--r--src/console/dlt-control-common.c588
-rw-r--r--src/console/dlt-control-common.h82
-rw-r--r--src/console/logstorage/CMakeLists.txt41
-rw-r--r--src/console/logstorage/dlt-logstorage-common.c318
-rw-r--r--src/console/logstorage/dlt-logstorage-common.h83
-rw-r--r--src/console/logstorage/dlt-logstorage-ctrl.c551
-rw-r--r--src/console/logstorage/dlt-logstorage-ctrl.h30
-rw-r--r--src/console/logstorage/dlt-logstorage-list.c236
-rw-r--r--src/console/logstorage/dlt-logstorage-list.h33
-rw-r--r--src/console/logstorage/dlt-logstorage-prop.h72
-rw-r--r--src/console/logstorage/dlt-logstorage-udev.c448
-rw-r--r--src/console/logstorage/dlt-logstorage-udev.h39
14 files changed, 2537 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e8e961a..32ff107 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,6 +70,8 @@ option(WITH_DLT_DBUS "Set to ON to build src/dbus binaries"
option(WITH_DLT_TESTS "Set to ON to build src/test binaries" ON)
option(WITH_DLT_CXX11_EXT "Set to ON to build C++11 extensions" OFF)
option(WITH_DLT_COREDUMPHANDLER "EXPERIMENTAL! Set to ON to build src/core_dump_handler binaries. EXPERIMENTAL" OFF)
+option(WITH_DLT_LOGSTORAGE_CTRL_UDEV "PROTOTYPE! Set to ON to build logstorage control application with udev support" OFF)
+option(WITH_DLT_LOGSTORAGE_CTRL_PROP "PROTOTYPE! Set to ON to build logstorage control application with proprietary support" OFF)
# RPM settings
set( GENIVI_RPM_RELEASE "1")#${DLT_REVISION}")
set( LICENSE "Mozilla Public License Version 2.0" )
@@ -93,6 +95,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/offlinelogstorage/
${CMAKE_SOURCE_DIR}/src/lib/
${CMAKE_SOURCE_DIR}/src/daemon/
+ ${CMAKE_SOURCE_DIR}/src/console/
${CMAKE_SOURCE_DIR}/systemd/3rdparty/
)
@@ -163,6 +166,14 @@ if(WITH_SYSTEMD OR WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD_JOURNAL)
add_subdirectory( systemd )
endif(WITH_SYSTEMD OR WITH_SYSTEMD_WATCHDOG OR WITH_SYSTEMD_JOURNAL)
+if(WITH_DLT_LOGSTORAGE_CTRL_UDEV)
+ add_definitions( -DDLT_LOGSTORAGE_CTRL_UDEV_ENABLE)
+endif(WITH_DLT_LOGSTORAGE_CTRL_UDEV)
+
+if(WITH_DLT_LOGSTORAGE_CTRL_PROP)
+ add_definitions( -DDLT_LOGSTORAGE_CTRL_PROP)
+endif(WITH_DLT_LOGSTORAGE_CTRL_PROP)
+
add_subdirectory( doc )
add_subdirectory( src )
add_subdirectory( include )
@@ -201,6 +212,8 @@ message( STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}" )
message( STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}" )
message( STATUS "CMAKE_HOST_SYSTEM_PROCESSOR = ${CMAKE_HOST_SYSTEM_PROCESSOR}" )
message( STATUS "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}" )
+message( STATUS "WITH_DLT_LOGSTORAGE_CTRL_UDEV = ${WITH_DLT_LOGSTORAGE_CTRL_UDEV}" )
+message( STATUS "WITH_DLT_LOGSTORAGE_CTRL_PROP = ${WITH_DLT_LOGSTORAGE_CTRL_PROP}" )
message( STATUS "Change a value with: cmake -D<Variable>=<Value>" )
message( STATUS "-------------------------------------------------------------------------------" )
message( STATUS )
diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt
index fde3fe3..f0a036a 100644
--- a/src/console/CMakeLists.txt
+++ b/src/console/CMakeLists.txt
@@ -30,6 +30,9 @@ add_executable(dlt-control ${dlt_control_SRCS} ${dlt_most_SRCS})
target_link_libraries(dlt-control dlt ${EXPAT_LIBRARIES})
set_target_properties(dlt-control PROPERTIES LINKER_LANGUAGE C)
+set(dlt_control_common_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/dlt-control-common.c)
+add_subdirectory( logstorage )
+
install(TARGETS dlt-convert dlt-receive dlt-control
RUNTIME DESTINATION bin
COMPONENT base)
diff --git a/src/console/dlt-control-common.c b/src/console/dlt-control-common.c
new file mode 100644
index 0000000..c3d82cf
--- /dev/null
+++ b/src/console/dlt-control-common.c
@@ -0,0 +1,588 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-control-common.c
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt-control-common.c **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com **
+** PURPOSE : **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: yes **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** cl Christoph Lipka ADIT **
+** fb Frederic Berat ADIT **
+*******************************************************************************/
+#define pr_fmt(fmt) "Common control: "fmt
+
+#include <errno.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "dlt_common.h"
+#include "dlt_protocol.h"
+#include "dlt_client.h"
+
+#include "dlt-control-common.h"
+
+#define DLT_CTRL_APID "DLTC"
+#define DLT_CTRL_CTID "DLTC"
+#define DLT_CTRL_SOCK "/tmp/dlt-ctrl.sock"
+
+#define DLT_RECEIVE_TEXTBUFSIZE 1024
+
+/** @brief Analyze the daemon answer
+ *
+ * This function as to be provided by the user of the connection.
+ *
+ * @param answer The textual answer of the daemon
+ * @param payload The daemons answer payload
+ * @param length The daemons answer payload length
+ *
+ * @return User defined.
+ */
+static int (*response_analyzer_cb)(char *, void *, int);
+
+static pthread_t daemon_connect_thread;
+static DltClient client;
+static int callback_return = -1;
+static pthread_mutex_t answer_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t answer_cond = PTHREAD_COND_INITIALIZER;
+
+static int local_verbose;
+static char local_ecuid[DLT_CTRL_ECUID_LEN]; /* Name of ECU */
+static long local_timeout;
+
+int get_verbosity(void)
+{
+ return local_verbose;
+}
+
+void set_verbosity(int v)
+{
+ local_verbose = !!v;
+}
+
+char *get_ecuid(void)
+{
+ return local_ecuid;
+}
+
+void set_ecuid(char *ecuid)
+{
+ if (local_ecuid != ecuid)
+ {
+ memset(local_ecuid, 0, DLT_CTRL_ECUID_LEN);
+ strncpy(local_ecuid, ecuid, DLT_CTRL_ECUID_LEN);
+ local_ecuid[DLT_CTRL_ECUID_LEN - 1] = '\0';
+ }
+}
+
+long get_timeout(void)
+{
+ return local_timeout;
+}
+
+void set_timeout(long t)
+{
+ local_timeout = DLT_CTRL_TIMEOUT;
+
+ if (t > 1)
+ {
+ local_timeout = t;
+ }
+ else
+ {
+ pr_error("Timeout to small. Set to default: %d",
+ DLT_CTRL_TIMEOUT);
+ }
+}
+
+/** @brief Send a message to the daemon through the socket.
+ *
+ * The socket as to be opened and active before sending.
+ *
+ * @param sock The socket to send the message through
+ * @param msg The message to be send in DLT format.
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+static int dlt_control_send_message_to_socket(int sock, DltMessage *msg)
+{
+ if (send(sock,
+ (const char *)(msg->headerbuffer + sizeof(DltStorageHeader)),
+ msg->headersize - sizeof(DltStorageHeader), 0) == -1)
+ {
+ pr_error("Sending message header failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ if (send(sock, (const char *) msg->databuffer, msg->datasize, 0) == -1)
+ {
+ pr_error("Sending message failed: %s\n", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+/** @brief Prepare the extra headers of a DLT message
+ *
+ * Modifies the extra headers of the message so that it can be sent.
+ *
+ * @param msg The message to be prepared
+ * @param header The base header to be used.
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+static int prepare_extra_headers(DltMessage *msg, uint8_t *header)
+{
+ int shift = 0;
+
+ pr_verbose("Preparing extra headers.\n");
+
+ if (!msg || !header)
+ {
+ return -1;
+ }
+
+ shift = sizeof(DltStorageHeader) +
+ sizeof(DltStandardHeader) +
+ DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp);
+
+ /* Set header extra parameters */
+ dlt_set_id(msg->headerextra.ecu, get_ecuid());
+
+ msg->headerextra.tmsp = dlt_uptime();
+
+ /* Copy header extra parameters to header buffer */
+ if (dlt_message_set_extraparameters(msg, get_verbosity()) == -1)
+ {
+ pr_error("Cannot copy header extra parameter\n");
+ return -1;
+ }
+
+ /* prepare extended header */
+ msg->extendedheader = (DltExtendedHeader *)(header + shift);
+
+ msg->extendedheader->msin = DLT_MSIN_CONTROL_REQUEST;
+
+ msg->extendedheader->noar = 1; /* one payload packet */
+
+ /* Dummy values have to be set */
+ dlt_set_id(msg->extendedheader->apid, DLT_CTRL_APID);
+ dlt_set_id(msg->extendedheader->ctid, DLT_CTRL_CTID);
+
+ return 0;
+}
+
+/** @brief Prepare the headers of a DLT message
+ *
+ * Modifies the headers of the message so that it can be sent.
+ *
+ * @param msg The message to be prepared
+ * @param header The base header to be used.
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+static int prepare_headers(DltMessage *msg, uint8_t *header)
+{
+ uint32_t len = 0;
+
+ pr_verbose("Preparing headers.\n");
+
+ if (!msg || !header)
+ {
+ return -1;
+ }
+
+ msg->storageheader = (DltStorageHeader *) header;
+
+ if (dlt_set_storageheader(msg->storageheader, "") == -1)
+ {
+ pr_error("Storage header initialization failed.\n");
+ return -1;
+ }
+
+ /* prepare standard header */
+ msg->standardheader =
+ (DltStandardHeader *) (header + sizeof(DltStorageHeader));
+
+ msg->standardheader->htyp = DLT_HTYP_WEID |
+ DLT_HTYP_WTMS | DLT_HTYP_UEH | DLT_HTYP_PROTOCOL_VERSION1;
+
+#if (BYTE_ORDER == BIG_ENDIAN)
+ msg->standardheader->htyp = (msg->standardheader->htyp | DLT_HTYP_MSBF);
+#endif
+
+ msg->standardheader->mcnt = 0;
+
+ /* prepare length information */
+ msg->headersize = sizeof(DltStorageHeader) +
+ sizeof(DltStandardHeader) +
+ sizeof(DltExtendedHeader) +
+ DLT_STANDARD_HEADER_EXTRA_SIZE(msg->standardheader->htyp);
+
+ len = msg->headersize - sizeof(DltStorageHeader) + msg->datasize;
+
+ if (len > UINT16_MAX)
+ {
+ pr_error("Message header is too long.\n");
+ return -1;
+ }
+
+ msg->standardheader->len = DLT_HTOBE_16(len);
+
+ return 0;
+}
+
+/** @brief Prepare a DLT message.
+ *
+ * The DLT message is built using the data given by the user.
+ * The data is basically composed of a buffer and a size.
+ *
+ * @param data The message body to be used to build the DLT message.
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+static DltMessage *dlt_control_prepare_message(DltControlMsgBody *data)
+{
+ DltMessage *msg = NULL;
+
+ pr_verbose("Preparing message.\n");
+
+ if (data == NULL)
+ {
+ pr_error("Data for message body is NULL\n");
+ return NULL;
+ }
+
+ msg = calloc(1, sizeof(DltMessage));
+
+ if (msg == NULL)
+ {
+ pr_error("Cannot allocate memory for Dlt Message\n");
+ return NULL;
+ }
+
+ if (dlt_message_init(msg, get_verbosity()) == -1)
+ {
+ pr_error("Cannot initialize Dlt Message\n");
+ free(msg);
+ return NULL;
+ }
+
+ /* prepare payload of data */
+ msg->databuffersize = msg->datasize = data->size;
+
+ /* Allocate memory for Dlt Message's buffer */
+ msg->databuffer = (uint8_t *)calloc(1, data->size);
+
+ if (msg->databuffer == NULL)
+ {
+ pr_error("Cannot allocate memory for data buffer\n");
+ free(msg);
+ return NULL;
+ }
+
+ /* copy data into message */
+ memcpy(msg->databuffer, data->data, data->size);
+
+ /* prepare storage header */
+ if (prepare_headers(msg, msg->headerbuffer))
+ {
+ dlt_message_free(msg, get_verbosity());
+ free(msg);
+ return NULL;
+ }
+
+ /* prepare extra headers */
+ if (prepare_extra_headers(msg, msg->headerbuffer))
+ {
+ dlt_message_free(msg, get_verbosity());
+ free(msg);
+ return NULL;
+ }
+
+ return msg;
+}
+
+/** @brief Initialize the connection with the daemon
+ *
+ * The connection is initialized using an internal callback. The user's
+ * response analyzer will be finally executed by this callback.
+ * The client pointer is used to established the connection.
+ *
+ * @param client A pointer to a valid client structure
+ * @param cb The internal callback to be executed while receiving a new message
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+static int dlt_control_init_connection(DltClient *client, void *cb)
+{
+ int (*callback)(DltMessage *message, void *data) = cb;
+
+ if (!cb || !client)
+ {
+ pr_error("%s Invalid parameters (%p, %p)\n", __func__, client, cb);
+ return -1;
+ }
+
+ pr_verbose("Initializing the connection.\n");
+ if (dlt_client_init(client, get_verbosity()) != 0)
+ {
+ pr_error("Failed to register callback (NULL)\n");
+ return -1;
+ }
+
+ dlt_client_register_message_callback(callback);
+
+ client->socketPath = DLT_CTRL_SOCK;
+ client->mode = DLT_CLIENT_MODE_UNIX;
+
+ return dlt_client_connect(client, get_verbosity());
+}
+
+/** @brief Daemon listener function
+ *
+ * This function will continuously read on the DLT socket, until an error occurs
+ * or the thread executing this function is canceled.
+ *
+ * @param data Thread parameter
+ *
+ * @return The thread parameter given as argument.
+ */
+static void *dlt_control_listen_to_daemon(void *data)
+{
+ pr_verbose("Ready to receive DLT answers.\n");
+ dlt_client_main_loop(&client, NULL, get_verbosity());
+ return data;
+}
+
+/** @brief Internal callback for DLT response
+ *
+ * This function is called by the dlt_client_main_loop once a response is read
+ * from the DLT socket.
+ * After some basic checks, the user's response analyzer is called. The return
+ * value of the analyzer is then provided back to the dlt_control_send_message
+ * function to be given back as a return value.
+ * As this function is called in a dedicated thread, the return value is
+ * provided using a global variable.
+ * Access to this variable is controlled through a dedicated mutex.
+ * New values are signaled using a dedicated condition variable.
+ *
+ * @param message The DLT answer
+ * @data Unused
+ *
+ * @return The analyzer return value or -1 on early errors.
+ */
+static int dlt_control_callback(DltMessage *message, void *data)
+{
+ char text[DLT_RECEIVE_TEXTBUFSIZE] = { 0 };
+ (void) data;
+
+ if (message == NULL)
+ {
+ pr_error("Received message is null\n");
+ return -1;
+ }
+
+ /* prepare storage header */
+ if (DLT_IS_HTYP_WEID(message->standardheader->htyp))
+ {
+ dlt_set_storageheader(message->storageheader, message->headerextra.ecu);
+ }
+ else
+ {
+ dlt_set_storageheader(message->storageheader, "LCTL");
+ }
+
+ dlt_message_header(message, text, DLT_RECEIVE_TEXTBUFSIZE, get_verbosity());
+
+ /* Extracting payload */
+ dlt_message_payload(message, text,
+ DLT_RECEIVE_TEXTBUFSIZE,
+ DLT_OUTPUT_ASCII,
+ get_verbosity());
+
+ /*
+ * Checking payload with the provided callback and return the result
+ */
+ pthread_mutex_lock(&answer_lock);
+ callback_return = response_analyzer_cb(text,
+ message->databuffer,
+ message->datasize);
+ pthread_cond_signal(&answer_cond);
+ pthread_mutex_unlock(&answer_lock);
+
+ return callback_return;
+}
+
+/** @brief Send a message to the daemon and wait for the asynchronous answer.
+ *
+ * The answer is received and analyzed by a dedicated thread. Thus we need
+ * to wait for the signal from this thread and then read the return value
+ * to be provided to the user.
+ * In case of timeout, this function fails.
+ * The message provided by the user is formated in DLT format before sending.
+ *
+ * @param body The message provided by the user
+ * @param timeout The time to wait before considering that no answer will come
+ *
+ * @return The user response analyzer return value, -1 in case of early error.
+ */
+int dlt_control_send_message(DltControlMsgBody *body, int timeout)
+{
+ struct timespec t;
+ DltMessage *msg = NULL;
+
+ if (!body)
+ {
+ pr_error("Invalid input (%p).\n", body);
+ return -1;
+ }
+
+ if (clock_gettime(CLOCK_REALTIME, &t) == -1)
+ {
+ pr_error("Cannot read system time.\n");
+ return -1;
+ }
+
+ t.tv_sec += timeout;
+
+ /* send command to daemon here */
+ msg = dlt_control_prepare_message(body);
+
+ if (msg == NULL)
+ {
+ pr_error("Control message preparation failed\n");
+ return -1;
+ }
+
+ pthread_mutex_lock(&answer_lock);
+
+ /* Re-init the return value */
+ callback_return = -1;
+
+ if (dlt_control_send_message_to_socket(client.sock, msg) != 0)
+ {
+ pr_error("Sending message to daemon failed\n");
+ free(msg);
+ return -1;
+ }
+
+ /* If we timeout the lock is not taken back */
+ if (!pthread_cond_timedwait(&answer_cond, &answer_lock, &t))
+ {
+ pthread_mutex_unlock(&answer_lock);
+ }
+
+ /* Destroying the message */
+ dlt_message_free(msg, get_verbosity());
+ free(msg);
+
+ /* At this point either the value is already correct, either it's still -1.
+ * Then, we don't care to lock the access.
+ */
+ return callback_return;
+}
+
+/** @brief Control communication initialization
+ *
+ * This will prepare the DLT connection and the thread dedicated to the
+ * response listening.
+ *
+ * @param response_analyzer User defined function used to analyze the response
+ * @param ecuid The ECUID to provide to the daemon
+ * @param verbosity The verbosity level
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+int dlt_control_init(int (*response_analyzer)(char *, void *, int),
+ char *ecuid,
+ int verbosity)
+{
+ if (!response_analyzer || !ecuid)
+ {
+ pr_error("Invalid input (%p %p).\n", response_analyzer, ecuid);
+ return -1;
+ }
+
+ response_analyzer_cb = response_analyzer;
+ set_ecuid(ecuid);
+ set_verbosity(verbosity);
+
+ if (dlt_control_init_connection(&client, dlt_control_callback) != 0)
+ {
+ pr_error("Connection initialization failed\n");
+ dlt_client_cleanup(&client, get_verbosity());
+ return -1;
+ }
+
+ /* Contact DLT daemon */
+ if (pthread_create(&daemon_connect_thread,
+ NULL,
+ dlt_control_listen_to_daemon,
+ NULL) != 0)
+ {
+ pr_error("Cannot create thread to communicate with DLT daemon.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/** @brief Control communication clean-up
+ *
+ * Cancels the listener thread and clean=up the dlt client structure.
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+int dlt_control_deinit(void)
+{
+ /* Stopping the listener thread */
+ pthread_cancel(daemon_connect_thread);
+ /* Closing the socket */
+ return dlt_client_cleanup(&client, get_verbosity());
+}
diff --git a/src/console/dlt-control-common.h b/src/console/dlt-control-common.h
new file mode 100644
index 0000000..b8d712f
--- /dev/null
+++ b/src/console/dlt-control-common.h
@@ -0,0 +1,82 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-control-common.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+#ifndef _DLT_CONTROL_COMMON_H_
+#define _DLT_CONTROL_COMMON_H_
+
+#include <stdio.h>
+
+#include "dlt_common.h"
+
+#define DLT_CTRL_TIMEOUT 10
+
+#define DLT_CTRL_ECUID_LEN 10
+
+#ifndef pr_fmt
+# define pr_fmt(fmt) fmt
+#endif
+
+#ifndef USE_STDOUT
+# define PRINT_OUT stderr
+#else
+# define PRINT_OUT stdout
+#endif
+
+#define pr_error(fmt, ...) \
+ ({ fprintf(PRINT_OUT, pr_fmt(fmt), ## __VA_ARGS__); fflush(PRINT_OUT); })
+#define pr_verbose(fmt, ...) \
+ ({ if (get_verbosity()) { fprintf(PRINT_OUT, pr_fmt(fmt), ## __VA_ARGS__); fflush(PRINT_OUT); } })
+
+#define DLT_CTRL_DEFAULT_ECUID "ECU1"
+
+/* To be used as Dlt Message body when sending to DLT daemon */
+typedef struct
+{
+ void *data; /**< data to be send to DLT Daemon */
+ int size; /**< size of that data */
+} DltControlMsgBody;
+
+/* As verbosity, ecuid and timeout are needed during the communication,
+ * defining getter and setters here.
+ * Then there is no need to define them in the control's user application.
+ */
+int get_verbosity(void);
+void set_verbosity(int);
+
+char *get_ecuid(void);
+void set_ecuid(char *);
+
+long get_timeout(void);
+void set_timeout(long);
+
+/* Initialize the connection to the daemon */
+int dlt_control_init(int (*response_analyser)(char *, void *, int),
+ char *ecuid,
+ int verbosity);
+
+/* Send a message to the daemon. The call is not thread safe. */
+int dlt_control_send_message(DltControlMsgBody *, int);
+
+/* Destroys the connection to the daemon */
+int dlt_control_deinit(void);
+#endif
diff --git a/src/console/logstorage/CMakeLists.txt b/src/console/logstorage/CMakeLists.txt
new file mode 100644
index 0000000..830bf5a
--- /dev/null
+++ b/src/console/logstorage/CMakeLists.txt
@@ -0,0 +1,41 @@
+#######
+# @licence make begin@
+# SPDX license identifier: MPL-2.0
+#
+# Copyright (C) 2015, ADIT GmbH
+#
+# This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
+#
+# This Source Code Form is subject to the terms of the
+# Mozilla Public License (MPL), v. 2.0.
+# If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# For further information see http://www.genivi.org/.
+# @licence end@
+#######
+add_definitions( -Werror )
+
+if(WITH_DLT_LOGSTORAGE_CTRL_UDEV AND WITH_DLT_LOGSTORAGE_CTRL_PROP)
+ set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-prop.c dlt-logstorage-udev.c dlt-logstorage-list.c)
+elseif(WITH_DLT_LOGSTORAGE_CTRL_PROP)
+ set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-prop.c dlt-logstorage-list.c)
+elseif(WITH_DLT_LOGSTORAGE_CTRL_UDEV)
+ set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-udev.c dlt-logstorage-list.c)
+else(WITH_DLT_LOGSTORAGE_CTRL_UDEV)
+ set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-list.c)
+endif(WITH_DLT_LOGSTORAGE_CTRL_UDEV AND WITH_DLT_LOGSTORAGE_CTRL_PROP)
+
+add_executable(dlt-logstorage-ctrl ${dlt_logstorage_ctrl_SRCS} ${dlt_control_common_SRCS} ${dlt_most_SRCS} ${CMAKE_SOURCE_DIR}/systemd/3rdparty/sd-daemon.c )
+
+if(WITH_DLT_LOGSTORAGE_CTRL_UDEV)
+ target_link_libraries(dlt-logstorage-ctrl dlt udev ${EXPAT_LIBRARIES})
+else(WITH_DLT_LOGSTORAGE_CTRL_UDEV)
+ target_link_libraries(dlt-logstorage-ctrl dlt ${EXPAT_LIBRARIES})
+endif(WITH_DLT_LOGSTORAGE_CTRL_UDEV)
+
+set_target_properties(dlt-logstorage-ctrl PROPERTIES LINKER_LANGUAGE C)
+
+install(TARGETS dlt-logstorage-ctrl
+ RUNTIME DESTINATION bin
+ COMPONENT base)
diff --git a/src/console/logstorage/dlt-logstorage-common.c b/src/console/logstorage/dlt-logstorage-common.c
new file mode 100644
index 0000000..a2f60a0
--- /dev/null
+++ b/src/console/logstorage/dlt-logstorage-common.c
@@ -0,0 +1,318 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2013 - 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2013 - 2015
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-logstorage-common.c
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt-logstorage-common.c **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com **
+** Frederic Berat fberat@de.adit-jv.com **
+** PURPOSE : **
+** **
+** REMARKS : Code extracted from dlt-control-common.c and reworked. **
+** **
+** PLATFORM DEPENDANT [yes/no]: yes **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** cl Christoph Lipka ADIT **
+** fb Frederic Berat ADIT **
+*******************************************************************************/
+#define pr_fmt(fmt) "Logstorage common: "fmt
+
+#include <errno.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "dlt_common.h"
+#include "dlt_protocol.h"
+#include "dlt_client.h"
+
+#include "dlt-control-common.h"
+#include "dlt-logstorage-common.h"
+
+#ifdef DLT_LOGSTORAGE_CTRL_UDEV_ENABLE
+#include "dlt-logstorage-udev.h"
+#endif
+
+#include "dlt-logstorage-prop.h"
+
+static struct LogstorageOptions {
+ int event_type; /**< EVENT_UNMOUNTING/EVENT_MOUNTED */
+ char device_path[DLT_MOUNT_PATH_MAX]; /**< Default Mount path */
+ DltLogstorageHandler handler_type; /**< be controlled by udev or prop */
+ long timeout; /**< Default timeout */
+} g_options = {
+ .event_type = EVENT_MOUNTED,
+ .handler_type = CTRL_NOHANDLER,
+};
+
+DltLogstorageHandler get_handler_type(void)
+{
+ return g_options.handler_type;
+}
+
+void set_handler_type(char *type)
+{
+ g_options.handler_type = CTRL_UDEV;
+
+ if (type && check_proprietary_handling(type))
+ {
+ g_options.handler_type = CTRL_PROPRIETARY;
+ }
+}
+
+int get_default_event_type(void)
+{
+ return g_options.event_type;
+}
+
+void set_default_event_type(long type)
+{
+ g_options.event_type = !!type;
+}
+
+char *get_default_path(void)
+{
+ return g_options.device_path;
+}
+
+void set_default_path(char *path)
+{
+ memset(g_options.device_path, 0, DLT_MOUNT_PATH_MAX);
+ strncpy(g_options.device_path, path, DLT_MOUNT_PATH_MAX - 1);
+}
+
+/* Used by the handlers */
+static DltLogstorageCtrl lctrl;
+
+DltLogstorageCtrl *get_logstorage_control(void)
+{
+ return &lctrl;
+}
+
+void *dlt_logstorage_get_handler_cb(void)
+{
+ return lctrl.callback;
+}
+
+int dlt_logstorage_get_handler_fd(void)
+{
+ return lctrl.fd;
+}
+
+/** @brief Initialized the handler based on configuration
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+int dlt_logstorage_init_handler(void)
+{
+ switch (get_handler_type())
+ {
+ case CTRL_PROPRIETARY:
+ return dlt_logstorage_prop_init();
+ case CTRL_UDEV:
+ default:
+#ifdef DLT_LOGSTORAGE_CTRL_UDEV_ENABLE
+ return dlt_logstorage_udev_init();
+#else
+ return -1;
+#endif
+ }
+}
+
+/** @brief Clean-up the handler based on configuration
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+int dlt_logstorage_deinit_handler(void)
+{
+ switch (get_handler_type())
+ {
+ case CTRL_PROPRIETARY:
+ return dlt_logstorage_prop_deinit();
+ case CTRL_UDEV:
+ default:
+#ifdef DLT_LOGSTORAGE_CTRL_UDEV_ENABLE
+ return dlt_logstorage_udev_deinit();
+#else
+ return -1;
+#endif
+ }
+}
+
+/** @brief Search for config file in given mount point
+ *
+ * The file is searched at the top directory. The function exits once it
+ * founds it.
+ *
+ * @param mnt_point The mount point to check
+ *
+ * @return 1 if the file is found, 0 otherwise.
+ */
+int dlt_logstorage_check_config_file(char *mnt_point)
+{
+ struct dirent **files;
+ int n;
+ int i = 0;
+ int ret = 0;
+
+ if ((mnt_point == NULL) || (mnt_point[0] == '\0'))
+ {
+ pr_error("Mount point missing.\n");
+ return ret;
+ }
+
+ pr_verbose("Now scanning %s\n", mnt_point);
+
+ n = scandir(mnt_point, &files, NULL, alphasort);
+
+ if (n <= 0)
+ {
+ pr_error("Cannot read mounted directory\n");
+ return ret;
+ }
+
+ do
+ {
+ pr_verbose("Checking %s.\n", files[i]->d_name);
+
+ if (strncmp(files[i]->d_name, CONF_NAME, strlen(CONF_NAME)) == 0)
+ {
+ /* We found it ! */
+ pr_verbose("File found.\n");
+ ret = 1;
+ break;
+ }
+ }
+ while (++i < n);
+
+ for (i = 0 ; i < n ; i++)
+ {
+ free(files[i]);
+ }
+
+ free(files);
+ return ret;
+}
+
+/** @brief Prepares the body of the message to be send to DLT
+ *
+ * @param body A pointer to the MsgBody structure pointer
+ * @param conn_type The type of the event (Mounted/Unmounting)
+ * @param path The mount point path.
+ *
+ * @return The body once built or NULL.
+ */
+static DltControlMsgBody *prepare_message_body(DltControlMsgBody **body,
+ int conn_type,
+ char *path)
+{
+ DltServiceOfflineLogstorage *serv = NULL;
+
+ if (path == NULL)
+ {
+ pr_error("Mount path is uninitialized: %s\n", path);
+ return NULL;
+ }
+
+ pr_verbose("Sending event %d for %s.\n", conn_type, path);
+
+ *body = calloc(1, sizeof(DltControlMsgBody));
+
+ if (!*body)
+ {
+ pr_error("Not able to allocate memory for body.\n");
+ return *body;
+ }
+
+ (*body)->data = calloc(1, sizeof(DltServiceOfflineLogstorage));
+
+ if (!(*body)->data)
+ {
+ free(*body);
+ *body = NULL;
+ pr_error("Not able to allocate memory for body data.\n");
+ return NULL;
+ }
+
+ (*body)->size = sizeof(DltServiceOfflineLogstorage);
+
+ serv = (DltServiceOfflineLogstorage *) (*body)->data;
+
+ serv->service_id = DLT_SERVICE_ID_OFFLINE_LOGSTORAGE;
+ serv->connection_type = conn_type;
+ /* mount_point is DLT_MOUNT_PATH_MAX + 1 long,
+ * and the memory is already zeroed.
+ */
+ strncpy(serv->mount_point, path, DLT_MOUNT_PATH_MAX);
+
+ pr_verbose("Body is now ready.\n");
+
+ return *body;
+}
+
+/** @brief Send a logstorage event to DLT
+ *
+ * @param type The type of the event (Mounted/Unmounting)
+ * @param mount_point The mount point for this event
+ *
+ * @return 0 On success, -1 otherwise.
+ */
+int dlt_logstorage_send_event(int type, char *mount_point)
+{
+ int ret = 0;
+ DltControlMsgBody *msg_body = NULL;
+
+ /* mount_point is checked against NULL in the preparation */
+ if (!prepare_message_body(&msg_body, type, mount_point))
+ {
+ pr_error("Data for Dlt Message body is NULL\n");
+ return -1;
+ }
+
+ ret = dlt_control_send_message(msg_body, get_timeout());
+
+ free(msg_body->data);
+ free(msg_body);
+
+ return ret;
+}
diff --git a/src/console/logstorage/dlt-logstorage-common.h b/src/console/logstorage/dlt-logstorage-common.h
new file mode 100644
index 0000000..712f2e3
--- /dev/null
+++ b/src/console/logstorage/dlt-logstorage-common.h
@@ -0,0 +1,83 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2013 - 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2013 - 2015
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-logstorage-common.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+#ifndef _DLT_LOGSTORAGE_COMMON_H_
+#define _DLT_LOGSTORAGE_COMMON_H_
+
+#define CONF_NAME "dlt_logstorage.conf"
+
+#define EVENT_UNMOUNTING 0
+#define EVENT_MOUNTED 1
+
+typedef enum
+{
+ CTRL_NOHANDLER = 0, /**< one shot application */
+ CTRL_UDEV, /**< Handles udev events */
+ CTRL_PROPRIETARY /**< Handles proprietary event */
+} DltLogstorageHandler;
+
+DltLogstorageHandler get_handler_type(void);
+void set_handler_type(char *);
+
+char *get_default_path(void);
+void set_default_path(char *);
+
+int get_default_event_type(void);
+void set_default_event_type(long type);
+
+typedef struct {
+ int fd;
+ int (*callback)(void); /* callback for event handling */
+ void *prvt; /* Private data */
+} DltLogstorageCtrl;
+
+/* Get a reference to the logstorage control instance */
+DltLogstorageCtrl *get_logstorage_control(void);
+void *dlt_logstorage_get_handler_cb(void);
+int dlt_logstorage_get_handler_fd(void);
+int dlt_logstorage_init_handler(void);
+int dlt_logstorage_deinit_handler(void);
+
+/**
+ * Send an event to the dlt daemon
+ *
+ * @param type Event type (EVENT_UNMOUNTING/EVENT_MOUNTED)
+ * @param mount_point The mount point path concerned by this event
+ *
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_send_event(int, char *);
+
+/** @brief Search for config file in given mount point
+ *
+ * The file is searched at the top directory. The function exits once it
+ * founds it.
+ *
+ * @param mnt_point The mount point to check
+ *
+ * @return 1 if the file is found, 0 otherwise.
+ */
+int dlt_logstorage_check_config_file(char *);
+
+#endif
diff --git a/src/console/logstorage/dlt-logstorage-ctrl.c b/src/console/logstorage/dlt-logstorage-ctrl.c
new file mode 100644
index 0000000..b4d2b92
--- /dev/null
+++ b/src/console/logstorage/dlt-logstorage-ctrl.c
@@ -0,0 +1,551 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2013 - 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO. *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2013 - 2015
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-logstorage-ctrl.c
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt-logstorage-ctrl.c **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Syed Hameed shameed@jp.adit-jv.com **
+** Christoph Lipka clipka@jp.adit-jv.com **
+** AnithaAmmaji.baggam@in.bosch.com **
+** Frederic Berat fberat@de.adit-jv.com **
+** PURPOSE : **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: yes **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** sh Syed Hameed ADIT **
+** cl Christoph Lipka ADIT **
+** BA Anitha BA ADIT **
+** fb Frederic Berat ADIT **
+*******************************************************************************/
+
+#define pr_fmt(fmt) "Logstorage control: "fmt
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+
+#include <sys/epoll.h>
+
+#include "sd-daemon.h"
+
+#include "dlt_protocol.h"
+#include "dlt_client.h"
+#include "dlt-control-common.h"
+#include "dlt-logstorage-common.h"
+#include "dlt-logstorage-ctrl.h"
+
+#define EPOLL_MAX_EVENTS 10
+#define EPOLL_TIME_OUT 500
+
+#define DLT_LOGSTORAGE_CTRL_EXIT 1
+static int must_exit;
+static int efd;
+
+/** @brief Triggers the application exit
+ *
+ * The application will exit on next epoll timeout.
+ */
+void dlt_logstorage_exit(void)
+{
+ must_exit = DLT_LOGSTORAGE_CTRL_EXIT;
+}
+
+/** @brief Check if the application must exit
+ *
+ * The application will exit on next epoll timeout.
+ */
+int dlt_logstorage_must_exit(void)
+{
+ return must_exit;
+}
+
+/** @brief Signal handler.
+ *
+ * Triggers the exit of the application in case of specific signals
+ *
+ * @param signo The value of the signal received.
+ */
+static void catch_signal(int signo)
+{
+ if (signo)
+ {
+ pr_error("Signal %d received, exiting.", signo);
+ dlt_logstorage_exit();
+ }
+}
+
+/** @brief Install a handler for some signals
+ *
+ * Handler are installed on exit related signals. That allows to exit from
+ * the main loop gracefully.
+ */
+static void install_signal_handler(void)
+{
+ int signals[] = { SIGINT, SIGQUIT, SIGTERM, 0 };
+ unsigned int i;
+ struct sigaction sa;
+
+ pr_verbose("Installing signal handler.\n");
+
+ /* install a signal handler for the above listed signals */
+ for (i = 0 ; signals[i] ; i++)
+ {
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = catch_signal;
+
+ if (sigaction(signals[i], &sa, NULL) < 0)
+ {
+ pr_error("Failed to install signal %u handler. Error: %s\n",
+ signals[i], strerror(errno));
+ }
+ }
+}
+
+#define MAX_RESPONSE_LENGTH 32
+/** @brief Analyze the daemon answer to a request
+ *
+ * This function checks whether if the daemon answered positively to
+ * the request or not.
+ *
+ * @param data The textual answer
+ * @param payload The answer payload
+ * @param len The answer payload length
+ * @return 0 on success, -1 otherwise.
+ */
+static int analyze_response(char *data, void *payload, int len)
+{
+ int ret = -1;
+ char resp_ok[MAX_RESPONSE_LENGTH] = { 0 };
+
+ if (data == NULL || payload == NULL)
+ {
+ return -1;
+ }
+
+ /* satisfy compiler */
+ payload = payload;
+ len = len;
+
+ snprintf(resp_ok,
+ MAX_RESPONSE_LENGTH,
+ "service(%u), ok",
+ DLT_SERVICE_ID_OFFLINE_LOGSTORAGE);
+
+ if (strncmp(data, resp_ok, strlen(resp_ok)) == 0)
+ {
+ ret = 0;
+ }
+
+ pr_verbose("Response received: '%s'\n", data);
+ pr_verbose("Response expected: '%s'\n", resp_ok);
+
+ return ret;
+}
+
+/** @brief Add a new event to watch to the epoll instance
+ *
+ * This function could be exported to be used by udev/prop so that they can
+ * register several events.
+ * There is no remove function as the removal is done on efd closure.
+ *
+ * @param fd The file descriptor to watch
+ * @param cb The callback to be called on event.
+ *
+ * @return epoll_ctrl return value, or -1 on earlier failure.
+ */
+static int dlt_logstorage_ctrl_add_event(int fd, void *cb)
+{
+ struct epoll_event event;
+
+ if ((fd < 0) || !cb)
+ {
+ pr_error("Wrong parameter to add event (%d %p)\n", fd, cb);
+ return -1;
+ }
+
+ pr_verbose("Setting up the event handler with (%d, %p).\n", fd, cb);
+
+ event.data.ptr = cb;
+ event.events = EPOLLIN | EPOLLET;
+
+ return epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event);
+}
+
+/** @brief Main execution loop
+ *
+ * Waits on events from the epoll fd, and executes the callbacks retrieved
+ * back from the event structure.
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+static int dlt_logstorage_ctrl_execute_event_loop(int efd)
+{
+ struct epoll_event *events;
+ int i;
+ int ret = 0;
+ int n = 0;
+
+ events = calloc(10, sizeof(struct epoll_event));
+
+ if (!events)
+ {
+ pr_error("No memory available for events.\n");
+ return -1;
+ }
+
+ n = epoll_wait(efd, events, EPOLL_MAX_EVENTS, EPOLL_TIME_OUT);
+
+ if (n < 0)
+ {
+ pr_error("epoll_wait error: %s\n", strerror(errno));
+
+ if (errno == EINTR)
+ {
+ /* Only exit if the daemon has received QUIT/INT/TERM */
+ free(events);
+ return 0;
+ }
+
+ free(events);
+ return -1;
+ }
+
+ for (i = 0 ; i < n ; i++)
+ {
+ int (*callback)() = events[i].data.ptr;
+
+ if (!(events[i].events & (EPOLLIN | EPOLLET)))
+ {
+ pr_error("Error while polling. Event received: 0x%x\n",
+ events[i].events);
+ /* We only support one event producer.
+ * Error means that this producer died.
+ */
+ pr_error("Now closing fd and exiting.\n");
+ close(events[i].data.fd);
+ dlt_logstorage_exit();
+ ret = -1;
+ break;
+ }
+
+ if (!callback)
+ {
+ pr_error("Callback not found, exiting.\n");
+ dlt_logstorage_exit();
+ ret = -1;
+ break;
+ }
+
+ pr_verbose("Got new event, calling %p.\n", callback);
+
+ if (callback() < 0)
+ {
+ pr_error("Error while calling the callback, exiting.\n");
+ dlt_logstorage_exit();
+ ret = -1;
+ break;
+ }
+ }
+
+ free(events);
+ return ret;
+}
+
+/** @brief Start event loop and receive messages from DLT.
+ *
+ * The function will first install the signal handler,
+ * then create the epoll instance, initialize the communication controller,
+ * initialize the event handler and finally start the polling.
+ *
+ * @return 0 on success, -1 on error
+ */
+static int dlt_logstorage_ctrl_setup_event_loop(void)
+{
+ int ret = 0;
+
+ install_signal_handler();
+
+ pr_verbose("Creating epoll instance.\n");
+ efd = epoll_create1(0);
+
+ if (efd == -1)
+ {
+ pr_error("epoll_create error: %s\n", strerror(errno));
+ dlt_logstorage_exit();
+ return -errno;
+ }
+
+ /* Initializing the communication with the daemon */
+ while (dlt_control_init(analyze_response, get_ecuid(), get_verbosity()) &&
+ !dlt_logstorage_must_exit())
+ {
+ pr_error("Failed to initialize connection with the daemon.\n");
+ pr_error("Retrying to connect in %lds.\n", get_timeout());
+ sleep(get_timeout());
+ }
+
+ if (dlt_logstorage_must_exit())
+ {
+ pr_verbose("Exiting.\n");
+ return 0;
+ }
+
+ pr_verbose("Initializing event generator.\n");
+
+ if (dlt_logstorage_init_handler() < 0)
+ {
+ pr_error("Failed to initialize handler.\n");
+ dlt_control_deinit();
+ return -1;
+ }
+
+ if (dlt_logstorage_ctrl_add_event(dlt_logstorage_get_handler_fd(),
+ dlt_logstorage_get_handler_cb()) < 0)
+ {
+ pr_error("epoll_ctl error: %s\n", strerror(errno));
+ dlt_logstorage_exit();
+ }
+
+ while (!dlt_logstorage_must_exit() && (ret == 0))
+ {
+ ret = dlt_logstorage_ctrl_execute_event_loop(efd);
+ }
+
+ /* Clean up */
+ close(efd);
+
+ dlt_logstorage_deinit_handler();
+ dlt_control_deinit();
+
+ return ret;
+}
+
+/** @brief Send a single command to DLT daemon and wait for response
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+static int dlt_logstorage_ctrl_single_request()
+{
+ int ret = 0;
+ /* Check if a 'CONF_NAME' file is present at the given path */
+ if (!dlt_logstorage_check_config_file(get_default_path()))
+ {
+ pr_error("No '%s' file available at: %s\n",
+ CONF_NAME,
+ get_default_path());
+ return -1;
+ }
+
+ /* Initializing the communication with the daemon */
+ while (dlt_control_init(analyze_response, get_ecuid(), get_verbosity()) &&
+ !dlt_logstorage_must_exit())
+ {
+ pr_error("Failed to initialize connection with the daemon.\n");
+ pr_error("Retrying to connect in %lds.\n", get_timeout());
+ sleep(get_timeout());
+ }
+
+ pr_verbose("event type is [%d]\t device path is [%s]\n",
+ get_default_event_type(),
+ get_default_path());
+
+ ret = dlt_logstorage_send_event(get_default_event_type(),
+ get_default_path());
+
+ dlt_control_deinit();
+
+ return ret;
+}
+
+/** @brief Print out the application help
+ */
+static void usage(void)
+{
+ printf("Usage: dlt-logstorage-ctrl [options]\n");
+ printf("Send a trigger to DLT daemon to connect/disconnect"
+ "a certain logstorage device\n");
+ printf("\n");
+ printf("Options:\n");
+ printf(" -c Connection type: connect = 1, disconnect = 0\n");
+ printf(" -d[prop] Run as daemon: prop = use proprietary handler\n");
+ printf(" 'prop' may be replaced by any meaningful word\n");
+ printf(" -e Set ECU ID (Default: %s)\n", DLT_CTRL_DEFAULT_ECUID);
+ printf(" -h Usage\n");
+ printf(" -p Mount point path\n");
+ printf(" -t Specify connection timeout (Default: %ds)\n",
+ DLT_CTRL_TIMEOUT);
+ printf(" -v Set verbose flag (Default:%d)\n", get_verbosity());
+}
+
+/** @brief Parses the application arguments
+ *
+ * The arguments are parsed and saved in static structure for future use.
+ *
+ * @param argc The amount of arguments
+ * @param argv The table of arguments
+ *
+ * @return 0 on success, -1 otherwise
+ */
+static int parse_args(int argc, char *argv[])
+{
+ int c = -1;
+
+ while ((c = getopt(argc, argv, ":t:he:p:d::c:v")) != -1)
+ {
+ switch (c)
+ {
+ case 't':
+ set_timeout(strtol(optarg, NULL, 10));
+ break;
+ case 'h':
+ usage();
+ return -1;
+ case 'e':
+ set_ecuid(optarg);
+ break;
+ case 'd':
+ pr_verbose("Choosing handler.\n");
+ set_handler_type(optarg);
+ pr_verbose("Handler chosen: %d.\n", get_handler_type());
+ break;
+ case 'p':
+
+ if (strlen(optarg) >= DLT_MOUNT_PATH_MAX)
+ {
+ pr_error("Mount path '%s' too long\n", optarg);
+ return -1;
+ }
+
+ set_default_path(optarg);
+ break;
+ case 'c':
+ set_default_event_type(strtol(optarg, NULL, 10));
+ break;
+ case 'v':
+ set_verbosity(1);
+ pr_verbose("Now in verbose mode.\n");
+ break;
+ case ':':
+ pr_error("Option -%c requires an argument.\n", optopt);
+ usage();
+ return -1;
+ case '?':
+
+ if (isprint(optopt))
+ {
+ pr_error("Unknown option -%c.\n", optopt);
+ }
+ else
+ {
+ pr_error("Unknown option character \\x%x.\n", optopt);
+ }
+
+ usage();
+ return -1;
+ default:
+ pr_error("Try %s -h for more information.\n", argv[0]);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/** @brief Entry point
+ *
+ * Execute the argument parser and call the main feature accordingly.
+ *
+ * @param argc The amount of arguments
+ * @param argv The table of arguments
+ *
+ * @return 0 on success, -1 otherwise
+ */
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+
+ set_ecuid(DLT_CTRL_DEFAULT_ECUID);
+ set_timeout(DLT_CTRL_TIMEOUT);
+
+ /* Get command line arguments */
+ if (parse_args(argc, argv) != 0)
+ {
+ return -1;
+ }
+
+ /* all parameter valid, start communication with daemon or setup
+ * communication with control daemon */
+ if (get_handler_type() == CTRL_NOHANDLER)
+ {
+ pr_verbose("One shot.\n");
+
+ ret = dlt_logstorage_ctrl_single_request();
+ if (ret < 0)
+ {
+ pr_error("Message failed to be send. Please check DLT config.\n");
+ }
+ }
+ else
+ {
+ pr_verbose("Entering in daemon mode.\n");
+
+ /* Let's daemonize */
+ if (sd_notify(0, "READY=1") <= 0)
+ {
+ pr_verbose("SD notify failed, manually daemonizing.\n");
+
+ /* No message can be sent or Systemd is not available.
+ * Daemonizing manually.
+ */
+ if (daemon(1, 1))
+ {
+ pr_error("Failed to daemonize: %s\n", strerror(errno));
+ return EXIT_FAILURE;
+ }
+ }
+
+ pr_verbose("Executing the event loop\n");
+ ret = dlt_logstorage_ctrl_setup_event_loop();
+ }
+
+ pr_verbose("Exiting.\n");
+ return ret;
+}
diff --git a/src/console/logstorage/dlt-logstorage-ctrl.h b/src/console/logstorage/dlt-logstorage-ctrl.h
new file mode 100644
index 0000000..11abe10
--- /dev/null
+++ b/src/console/logstorage/dlt-logstorage-ctrl.h
@@ -0,0 +1,30 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2013 - 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2013 - 2015
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-logstorage-ctrl.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+#ifndef _DLT_LOGSTORAGE_CONTROL_H_
+#define _DLT_LOGSTORAGE_CONTROL_H_
+
+/* Triggers the exit at the end of the event */
+void dlt_logstorage_exit(void);
+
+#endif
diff --git a/src/console/logstorage/dlt-logstorage-list.c b/src/console/logstorage/dlt-logstorage-list.c
new file mode 100644
index 0000000..0b7a8c0
--- /dev/null
+++ b/src/console/logstorage/dlt-logstorage-list.c
@@ -0,0 +1,236 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2013 - 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Anitha.BA <anithaammaji.baggam@in.bosch.com> ADIT 2015
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-logstorage-list.c
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt-logstorage-list.c **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com **
+** Anitha.B.A anithaammaji.baggam@in.bosch.com **
+** Frederic Berat fberat@de.adit-jv.com **
+** **
+** PURPOSE : linked list implementation for storing the device info **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: yes **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** BA Anitha ADIT **
+** cl Christoph Lipka ADIT **
+** fb Frederic Berat ADIT **
+*******************************************************************************/
+#define pr_fmt(fmt) "Log storage list: "fmt
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "dlt_common.h"
+#include "dlt-control-common.h"
+#include "dlt-logstorage-common.h"
+
+static struct LogstorageDeviceInfo
+{
+ char *dev_node; /**< The device node */
+ char *mnt_point; /**< Mount point for this device */
+ struct LogstorageDeviceInfo *prev; /**< Previous element of the list */
+ struct LogstorageDeviceInfo *next; /**< Next element of the list */
+} *g_info;
+
+/** @brief Prints the device list in verbose mode
+ *
+ * This can be used to debug the behavior.
+ * Therefore, it's only available in verbose mode.
+ */
+void print_list()
+{
+ struct LogstorageDeviceInfo *ptr = g_info;
+ pr_verbose(" -------Device list-------\n");
+
+ while (ptr != NULL)
+ {
+ pr_verbose("%p:\t[%s][%s] \n", ptr, ptr->dev_node, ptr->mnt_point);
+ ptr = ptr->next;
+ }
+
+ pr_verbose(" -------Device list end-------\n\n");
+
+ return;
+}
+
+/** @brief Find element in the list based on device node
+ *
+ * Allows to check whether a device is already in the list or
+ * to find out the one to be removed.
+ *
+ * @param node The device node to look for
+ *
+ * @return The element of the list found, NULL either.
+ */
+static struct LogstorageDeviceInfo *logstorage_find_dev_info(const char *node)
+{
+ struct LogstorageDeviceInfo *ptr = g_info;
+
+ if (!node)
+ {
+ return NULL;
+ }
+
+ pr_verbose("Looking for %s.\n", node);
+
+ while (ptr != NULL)
+ {
+ if (strncmp(ptr->dev_node, node, DLT_MOUNT_PATH_MAX) == 0)
+ {
+ pr_verbose("%s found in %p.\n", node, ptr);
+ break;
+ }
+ else
+ {
+ ptr = ptr->next;
+ }
+ }
+
+ return ptr;
+}
+
+/** @brief Add new device in the list
+ *
+ * The device is only added if a configuration file has been found and
+ * if it's not already in the list.
+ *
+ * @param node The device node to add
+ * @param path The corresponding mount point path
+ *
+ * @return 0 on success, -1 in case of error.
+ */
+int logstorage_store_dev_info(const char *node, const char *path)
+{
+ struct LogstorageDeviceInfo *ptr = NULL;
+
+ if ((node == NULL) || (path == NULL))
+ {
+ pr_error("Invalid input\n");
+ return -1;
+ }
+
+ if (logstorage_find_dev_info(node))
+ {
+ pr_verbose("%s already in list.\n", node);
+ print_list();
+ return 0;
+ }
+
+ ptr = calloc(1, sizeof(struct LogstorageDeviceInfo));
+
+ if (ptr == NULL)
+ {
+ pr_error("Node creation failed\n");
+ return -1;
+ }
+
+ ptr->dev_node = strdup(node);
+ ptr->mnt_point = strndup(path, DLT_MOUNT_PATH_MAX);
+
+ /* Put it on head */
+ ptr->next = g_info;
+
+ if (g_info)
+ {
+ g_info->prev = ptr;
+ }
+
+ g_info = ptr;
+
+ pr_verbose("%s added to list.\n", node);
+ print_list();
+
+ return 0;
+}
+
+/** @brief Remove a device from the list
+ *
+ * If the device is removed from the list, the mount point
+ * pointer is given back to the caller. That means that
+ * he has to free it.
+ *
+ * @param node The device node to be removed
+ *
+ * @return the mount point if the node is found, NULL either.
+ */
+char *logstorage_delete_dev_info(const char *node)
+{
+ struct LogstorageDeviceInfo *del = NULL;
+ char *ret = NULL;
+
+ del = logstorage_find_dev_info(node);
+
+ if (del == NULL)
+ {
+ pr_verbose("%s not found in list.\n", node);
+ print_list();
+ return ret;
+ }
+
+ /* Has to be freed by the caller */
+ ret = del->mnt_point;
+
+ if (del->prev)
+ {
+ del->prev->next = del->next;
+ }
+
+ if (del->next)
+ {
+ del->next->prev = del->prev;
+ }
+
+ if (del == g_info)
+ {
+ g_info = g_info->next;
+ }
+
+ free(del->dev_node);
+ free(del);
+
+ pr_verbose("%s removed from list.\n", node);
+ print_list();
+
+ return ret;
+}
diff --git a/src/console/logstorage/dlt-logstorage-list.h b/src/console/logstorage/dlt-logstorage-list.h
new file mode 100644
index 0000000..3df2171
--- /dev/null
+++ b/src/console/logstorage/dlt-logstorage-list.h
@@ -0,0 +1,33 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2013 - 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Christoph Lipka clipka@jp.adit-jv.com
+ * \author Anitha BA <anithaammaji.baggam@in.bosch.com> ADIT 2015
+ * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-logstorage-list.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+#ifndef _DLT_LOGSTORAGE_LIST_H_
+#define _DLT_LOGSTORAGE_LIST_H_
+
+/* Return 0 it the node as been added (or is already present) */
+int logstorage_store_dev_info(const char *node, const char *path);
+/* Returns the mount point if node has been found and deleted. NULL either */
+char *logstorage_delete_dev_info(const char *node);
+
+#endif
diff --git a/src/console/logstorage/dlt-logstorage-prop.h b/src/console/logstorage/dlt-logstorage-prop.h
new file mode 100644
index 0000000..836dc99
--- /dev/null
+++ b/src/console/logstorage/dlt-logstorage-prop.h
@@ -0,0 +1,72 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2013 - 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-logstorage-udev.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+#ifndef _DLT_LOGSTORAGE_PROP_H_
+#define _DLT_LOGSTORAGE_PROP_H_
+
+#ifndef HAS_PROPRIETARY_LOGSTORAGE
+/** @brief Initialize proprietary connection
+ *
+ * @return 0
+ */
+static inline int dlt_logstorage_prop_init(void) {
+ return 0;
+}
+
+/** @brief Clean-up proprietary connection
+ *
+ * @return 0
+ */
+static inline int dlt_logstorage_prop_deinit(void) {
+ return 0;
+}
+
+/** @brief Check whether user wants to use proprietary handler
+ *
+ * @return 0
+ */
+static inline int check_proprietary_handling(char *type) {
+ (void)type; return 0;
+}
+#else
+/**
+ * Initialize proprietary connection
+ *
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_prop_init(void);
+
+/**
+ * Clean-up proprietary connection
+ *
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_prop_deinit(void);
+
+/**
+ * Check whether user wants to use proprietary event handler
+ *
+ * @return 1 if yes, 0 either.
+ */
+int check_proprietary_handling(char *);
+#endif /* HAS_PROPRIETARY_LOGSTORAGE */
+
+#endif /* _DLT_LOGSTORAGE_PROP_H_ */
diff --git a/src/console/logstorage/dlt-logstorage-udev.c b/src/console/logstorage/dlt-logstorage-udev.c
new file mode 100644
index 0000000..355977e
--- /dev/null
+++ b/src/console/logstorage/dlt-logstorage-udev.c
@@ -0,0 +1,448 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2013 - 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-logstorage-udev.c
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt-logstorage-udev.c **
+** **
+** TARGET : linux **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com **
+** Frederic Berat fberat@de.adit-jv.com **
+** **
+** PURPOSE : For udev-based handling of any device **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: yes **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** cl Christoph Lipka ADIT **
+** fb Frederic Berat ADIT **
+*******************************************************************************/
+
+#define pr_fmt(fmt) "Udev control: "fmt
+
+#include <libudev.h>
+#include <errno.h>
+#include <mntent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mount.h>
+
+#include "dlt-control-common.h"
+#include "dlt-logstorage-common.h"
+#include "dlt-logstorage-list.h"
+#include "dlt-logstorage-udev.h"
+
+typedef struct {
+ struct udev *udev; /**< Udev instance */
+ struct udev_monitor *mon; /**< Udev monitor instance */
+} LogstorageCtrlUdev;
+
+/** @brief Get mount point of a device node
+ *
+ * This function search for the mount point in /proc/mounts
+ * based on the device node.
+ *
+ * @param dev_node Device node as string
+ *
+ * @return mount path or NULL on error
+ */
+static char *dlt_logstorage_udev_get_mount_point(char *dev_node)
+{
+ struct mntent *ent;
+ FILE *f;
+ char *mnt_point = NULL;
+
+ if (dev_node == NULL)
+ {
+ return NULL;
+ }
+
+ f = setmntent("/proc/mounts", "r");
+
+ if (f == NULL)
+ {
+ pr_error("Cannot read /proc/mounts\n");
+ return NULL;
+ }
+
+ while (NULL != (ent = getmntent(f)))
+ {
+ if (strncmp(ent->mnt_fsname, dev_node, strlen(ent->mnt_fsname)) == 0)
+ {
+ mnt_point = strdup(ent->mnt_dir);
+
+ /* Remounting rw */
+ if (strlen(mnt_point))
+ {
+ /* capabilities needed. Thus we don't really car on failure.
+ * Therefor we can ignore the return value.
+ */
+ (void) mount(NULL, mnt_point, NULL, MS_REMOUNT, ent->mnt_opts);
+ }
+
+ break;
+ }
+ }
+
+ endmntent(f);
+
+ return mnt_point;
+}
+
+/** @brief Check if the daemon needs to be notified by the event
+ *
+ * On mount event:
+ * If the device mount point contains the DLT configuration file,
+ * the function will then send a message to the daemon.
+ * On Unmounting event:
+ * Check if the device was on the list, remove it and send the message
+ * to the daemon.
+ *
+ * @event The kind of event happening
+ * @part The device partition to be checked
+ *
+ * @return 0 on success, -1 if an error occured.
+ */
+static int check_mountpoint_from_partition(int event, struct udev_device *part)
+{
+ int logstorage_dev = 0;
+ char *mnt_point = NULL;
+ char *dev_node = NULL;
+ int ret = 0;
+
+ if (!part)
+ {
+ pr_verbose("No partition structure given.\n");
+ return -1;
+ }
+
+ pr_verbose("Checking mount point.\n");
+
+ if (!udev_device_get_devnode(part))
+ {
+ pr_verbose("Skipping as no devnode.\n");
+ return 0;
+ }
+
+ dev_node = strdup(udev_device_get_devnode(part));
+
+ if (event == EVENT_MOUNTED)
+ {
+ mnt_point = dlt_logstorage_udev_get_mount_point(dev_node);
+ logstorage_dev = dlt_logstorage_check_config_file(mnt_point);
+
+ if (logstorage_dev) /* Configuration file available, add node to internal list */
+ {
+ logstorage_store_dev_info(dev_node, mnt_point);
+ }
+ else
+ {
+ mnt_point = NULL;
+ }
+ }
+ else
+ {
+ /* remove device information */
+ mnt_point = logstorage_delete_dev_info(dev_node);
+ }
+
+ if (mnt_point)
+ {
+ ret = dlt_logstorage_send_event(event, mnt_point);
+
+ if (ret)
+ {
+ pr_error("Can't send event for %s to DLT.\n", mnt_point);
+ }
+ }
+
+ free(dev_node);
+ free(mnt_point);
+
+ return 0;
+}
+
+/** @brief Handles the udev events
+ *
+ * On event, it finds the corresponding action, and calls
+ * check_mountpoint_from_partition with the corresponding event.
+ *
+ * @return 0 on success, -1 on error.
+ */
+static int logstorage_udev_udevd_callback(void)
+{
+ const char *action;
+ int ret = 0;
+ DltLogstorageCtrl *lctrl = get_logstorage_control();
+ LogstorageCtrlUdev *prvt = NULL;
+ struct udev_device *partition = NULL;
+
+ if (!lctrl)
+ {
+ pr_error("Not able to get logstorage control instance.\n");
+ return -1;
+ }
+
+ prvt = (LogstorageCtrlUdev *)lctrl->prvt;
+
+ if (!prvt || !prvt->mon)
+ {
+ pr_error("Not able to get private data.\n");
+ return -1;
+ }
+
+ partition = udev_monitor_receive_device(prvt->mon);
+
+ if (!partition)
+ {
+ pr_error("Not able to get partition.\n");
+ return -1;
+ }
+
+ action = udev_device_get_action(partition);
+
+ if (!action)
+ {
+ pr_error("Not able to get action.\n");
+ udev_device_unref(partition);
+ return -1;
+ }
+
+ pr_verbose("%s action received from udev for %s.\n",
+ action,
+ udev_device_get_devnode(partition));
+
+ if (strncmp(action, "add", sizeof("add")) == 0)
+ {
+ /*TODO: This can be replaced by polling on /proc/mount.
+ * we could get event on modification, and keep track on a list
+ * of mounted devices. New devices could be check that way.
+ * That also would solve the unmount event issue.
+ * Then, udev is only interesting to simplify the check on new devices,
+ * and/or for hot unplug (without unmount).
+ */
+ usleep(500 * 1000);
+ ret = check_mountpoint_from_partition(EVENT_MOUNTED, partition);
+ }
+ else if (strncmp(action, "remove", sizeof("remove")) == 0)
+ {
+ ret = check_mountpoint_from_partition(EVENT_UNMOUNTING, partition);
+ }
+
+ udev_device_unref(partition);
+
+ return ret;
+}
+
+/** @brief Check all partitions on the system to find configuration file
+ *
+ * The function looks for block devices that are of "partition" type.
+ * Then, it gets the node, and call check_mountpoint_from_partition with it.
+ *
+ * @udev The udev device used to find all the nodes
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+static int dlt_logstorage_udev_check_mounted(struct udev *udev)
+{
+ /* Create a list of the devices in the 'partition' subsystem. */
+ struct udev_enumerate *enumerate = udev_enumerate_new(udev);
+ struct udev_list_entry *devices = NULL;
+ struct udev_list_entry *dev_list_entry = NULL;
+
+ if (!enumerate)
+ {
+ pr_error("Can't enumerate devices.\n");
+ return -1;
+ }
+
+ udev_enumerate_add_match_subsystem(enumerate, "block");
+ udev_enumerate_add_match_property(enumerate, "DEVTYPE", "partition");
+ udev_enumerate_scan_devices(enumerate);
+
+ devices = udev_enumerate_get_list_entry(enumerate);
+
+ /* For each list entry, get the corresponding device */
+ udev_list_entry_foreach(dev_list_entry, devices) {
+ const char *path;
+ struct udev_device *partition = NULL;
+
+ /* Get the filename of the /sys entry for the device
+ * and create a udev_device object representing it
+ */
+ path = udev_list_entry_get_name(dev_list_entry);
+ partition = udev_device_new_from_syspath(udev, path);
+
+ if (!partition)
+ {
+ continue;
+ }
+
+ pr_verbose("Found device %s %s %s.\n",
+ path,
+ udev_device_get_devnode(partition),
+ udev_device_get_devtype(partition));
+
+ /* Check the device and clean-up */
+ check_mountpoint_from_partition(EVENT_MOUNTED, partition);
+ udev_device_unref(partition);
+ }
+
+ /* Free the enumerator object */
+ udev_enumerate_unref(enumerate);
+
+ return 0;
+}
+
+/** @brief Clean-up the udev data
+ *
+ * That will destroy all the private data.
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+int dlt_logstorage_udev_deinit(void)
+{
+ DltLogstorageCtrl *lctrl = get_logstorage_control();
+ LogstorageCtrlUdev *prvt = NULL;
+
+ if (!lctrl)
+ {
+ return -1;
+ }
+
+ prvt = (LogstorageCtrlUdev *)lctrl->prvt;
+
+ if (prvt->mon)
+ {
+ udev_monitor_unref(prvt->mon);
+ }
+
+ if (prvt->udev)
+ {
+ udev_unref(prvt->udev);
+ }
+
+ free(prvt);
+ lctrl->prvt = NULL;
+
+ return 0;
+}
+
+/** @brief Initialize the private data
+ *
+ * That function will create the udev device and monitor.
+ *
+ * @return 0 on success, -1 otherwise.
+ */
+int dlt_logstorage_udev_init(void)
+{
+ int ret = 0;
+
+ DltLogstorageCtrl *lctrl = get_logstorage_control();
+ LogstorageCtrlUdev *prvt = NULL;
+
+ pr_verbose("Initializing.\n");
+
+ if (!lctrl)
+ {
+ pr_error("Not able to get logstorage control instance.\n");
+ return -1;
+ }
+
+ lctrl->prvt = calloc(1, sizeof(LogstorageCtrlUdev));
+
+ if (!lctrl->prvt)
+ {
+ pr_error("No memory to allocate private data.\n");
+ return -1;
+ }
+
+ prvt = (LogstorageCtrlUdev *)lctrl->prvt;
+
+ /* Initialize udev object */
+ prvt->udev = udev_new();
+
+ if (!prvt->udev)
+ {
+ pr_error("Cannot initialize udev object\n");
+ dlt_logstorage_udev_deinit();
+ return -1;
+ }
+
+ /* setup udev monitor which will report events when
+ * devices attached to the system change. Events include
+ * "add", "remove", "change", etc */
+ prvt->mon = udev_monitor_new_from_netlink(prvt->udev, "udev");
+
+ if (!prvt->mon)
+ {
+ pr_error("Cannot initialize udev monitor\n");
+ dlt_logstorage_udev_deinit();
+ return -1;
+ }
+
+ ret = udev_monitor_filter_add_match_subsystem_devtype(prvt->mon,
+ "block",
+ NULL);
+
+ if (ret)
+ {
+ pr_error("Cannot attach filter to monitor: %s.\n", strerror(-ret));
+ dlt_logstorage_udev_deinit();
+ return -1;
+ }
+
+ ret = udev_monitor_enable_receiving(prvt->mon);
+
+ if (ret < 0)
+ {
+ pr_error("Cannot start receiving: %s.\n", strerror(-ret));
+ dlt_logstorage_udev_deinit();
+ return -1;
+ }
+
+ /* get file descriptor */
+ lctrl->fd = udev_monitor_get_fd(prvt->mon);
+ /* set callback function */
+ lctrl->callback = &logstorage_udev_udevd_callback;
+
+ /* check if there is something already mounted */
+ return dlt_logstorage_udev_check_mounted(prvt->udev);
+}
diff --git a/src/console/logstorage/dlt-logstorage-udev.h b/src/console/logstorage/dlt-logstorage-udev.h
new file mode 100644
index 0000000..d202453
--- /dev/null
+++ b/src/console/logstorage/dlt-logstorage-udev.h
@@ -0,0 +1,39 @@
+/**
+ * @licence app begin@
+ * Copyright (C) 2013 - 2015 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015
+ * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015
+ *
+ * \file dlt-logstorage-udev.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+#ifndef _DLT_LOGSTORAGE_UDEV_H_
+#define _DLT_LOGSTORAGE_UDEV_H_
+
+/**
+ * Initialize udev connection
+ *
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_udev_init(void);
+
+/**
+ * Clean-up udev connection
+ *
+ * @return 0 on success, -1 on error
+ */
+int dlt_logstorage_udev_deinit(void);
+
+#endif