diff options
author | Christoph Lipka <clipka@de.adit-jv.com> | 2015-05-13 16:27:40 +0900 |
---|---|---|
committer | Alexander Wenzel <Alexander.AW.Wenzel@bmw.de> | 2015-07-30 10:22:22 +0200 |
commit | 5e0ebd746e5144f40e793a810c2faa1be4b27367 (patch) | |
tree | 32ccc695015cc247a75aa98358dd91b3a6e937f7 | |
parent | f4fc0063d0e4bf01e448e9671cab28d4bc287dda (diff) | |
download | DLT-daemon-5e0ebd746e5144f40e793a810c2faa1be4b27367.tar.gz |
Offline logstorage [4/4]: Control application
Signed-off-by: Christoph Lipka <clipka@de.adit-jv.com>
-rwxr-xr-x | src/console/CMakeLists.txt | 7 | ||||
-rw-r--r-- | src/console/dlt-logstorage-ctrl.c | 461 |
2 files changed, 468 insertions, 0 deletions
diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt index 58ca6d4..86ccbc8 100755 --- a/src/console/CMakeLists.txt +++ b/src/console/CMakeLists.txt @@ -30,7 +30,14 @@ 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_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c) +add_executable(dlt-logstorage-ctrl ${dlt_logstorage_ctrl_SRCS} ${dlt_most_SRCS}) +target_link_libraries(dlt-logstorage-ctrl dlt ${EXPAT_LIBRARIES}) +set_target_properties(dlt-logstorage-ctrl PROPERTIES LINKER_LANGUAGE C) install(TARGETS dlt-convert dlt-receive dlt-control RUNTIME DESTINATION bin COMPONENT base) +install(TARGETS dlt-logstorage-ctrl + RUNTIME DESTINATION bin + COMPONENT base) diff --git a/src/console/dlt-logstorage-ctrl.c b/src/console/dlt-logstorage-ctrl.c new file mode 100644 index 0000000..95162d2 --- /dev/null +++ b/src/console/dlt-logstorage-ctrl.c @@ -0,0 +1,461 @@ +/** + * @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.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 ** +** 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 ** +*******************************************************************************/ + +#include <netdb.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/uio.h> +#include <stdint.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <errno.h> +#include <pthread.h> + +#include "dlt_common.h" +#include "dlt_client.h" +#include "dlt_protocol.h" + +#define DLT_RECEIVE_TEXTBUFSIZE 1024 +#define DLT_DAEMON_ECUID_DEFAULT "ECU1" +#define DLT_DAEMON_ECUID_LEN 10 +#define DLT_LOGSTORAGE_CTRL_TIMEOUT 10 + +DltClient dltclient; + +/* Result of callback function */ +int g_logstorage_callback_return = -1; + +const char *serverIP = "localhost"; + +typedef struct +{ + int connection_type; /* Conntection Type: 1 (connect), 0 (disconnect) */ + int device_number; /* Number of Logstorage device [1 .. MAX DEVICES] */ + char ecuid[DLT_DAEMON_ECUID_LEN]; /* Name of ECU */ +} DltLogstorageCtrlData; + +void usage() +{ + 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 Device: [1 .. DLT_OFFLINE_LOGSTORAGE_MAX_DEVICES]\n"); + printf(" -e Set ECU ID (Default: %s\n", DLT_DAEMON_ECUID_DEFAULT); + printf(" -h Usage\n"); + printf(" -t Specify connection timeout (Default: %ds)\n", DLT_LOGSTORAGE_CTRL_TIMEOUT); +} + +int dlt_logstorage_message_callback(DltMessage *message,void *data); +int dlt_logstorage_analyze_response(char *data); + +/* + * Prepare request message and send to Dlt Daemon. Since Logstorage control application acts + * as Dlt client, we use the same functionality found in + * dlt_daemon_client.c: dlt_daemon_client_send_control_message() + */ +int dlt_send_logstorage_request(int sockid, int device_number, int connection_type, char *ecuid) +{ + DltMessage msg; + DltServiceOfflineLogstorage *req = NULL; + int32_t len = 0; + int ret = 0; + + /* Initialise new message */ + if (dlt_message_init(&msg, 0) == -1) + { + fprintf( stderr, "Cannot initialize DltMessage\n"); + return -1; + } + + msg.datasize = sizeof(DltServiceOfflineLogstorage); + + /* prepare payload of data */ + if (msg.databuffer && (msg.databuffersize < msg.datasize)) + { + free(msg.databuffer); + msg.databuffer = 0; + } + if (msg.databuffer == 0) + { + /* malloc databuffer for DltMessage */ + msg.databuffer = (uint8_t *) malloc(msg.datasize); + msg.databuffersize = msg.datasize; + } + if(msg.databuffer == 0) + { + fprintf( stderr, "Cannot allocate memory for data buffer\n"); + dlt_message_free(&msg, 0); + return -1; + } + + req = (DltServiceOfflineLogstorage*) msg.databuffer; + + req->service_id = DLT_SERVICE_ID_OFFLINE_LOGSTORAGE; + req->dev_num = device_number; + req->connection_type = connection_type; + dlt_set_id(req->comid,"remo"); + + /* prepare storage header */ + msg.storageheader = (DltStorageHeader*) msg.headerbuffer; + if (dlt_set_storageheader(msg.storageheader, "") == -1) + { + fprintf( stderr, "Init storage header failed\n"); + dlt_message_free(&msg, 0); + return -1; + } + + /* prepare standard header */ + msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + 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; + + /* Set header extra parameters */ + if (ecuid == NULL) + { + dlt_set_id(msg.headerextra.ecu,DLT_DAEMON_ECUID_DEFAULT); + } + else + { + dlt_set_id(msg.headerextra.ecu,ecuid); + } + + msg.headerextra.tmsp = dlt_uptime(); + + /* Copy header extra parameters to headerbuffer */ + if (dlt_message_set_extraparameters(&msg, 0) == -1) + { + fprintf( stderr, "Cannot copy header extra parameter\n"); + dlt_message_free(&msg,0); + return -1; + } + + /* prepare extended header */ + msg.extendedheader = (DltExtendedHeader*)(msg.headerbuffer + + sizeof(DltStorageHeader) + + sizeof(DltStandardHeader) + + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp) ); + + msg.extendedheader->msin = DLT_MSIN_CONTROL_REQUEST; + + msg.extendedheader->noar = 1; /* one payload packet */ + + /* Dummy values have to be set: Offline_Log_Storage_Control, Context1 */ + dlt_set_id(msg.extendedheader->apid, "OLSC"); + dlt_set_id(msg.extendedheader->ctid, "CON1"); + + /* 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) + { + fprintf( stderr, "Message header too long\n"); + dlt_message_free(&msg, 0); + return -1; + } + + msg.standardheader->len = DLT_HTOBE_16(len); + + /* Send via Socket */ + if (send(sockid, (const char *)(msg.headerbuffer+sizeof(DltStorageHeader)), msg.headersize-sizeof(DltStorageHeader), 0) == -1) + { + fprintf( stderr, "Sending message to socket failed: %s\n", strerror(errno)); + ret = -1; + } + + if (send(sockid, (const char *) msg.databuffer,msg.datasize, 0) == -1) + { + fprintf( stderr, "Sending message to socket failed: %s\n", strerror(errno)); + ret = -1; + } + + /* free message */ + if (dlt_message_free(&msg, 0) == -1) + { + fprintf( stderr, "free DltMessage failed\n"); + return -1; + } + + return ret; +} + +int dlt_logstorage_message_callback(DltMessage *message, void *data) +{ + char text[DLT_RECEIVE_TEXTBUFSIZE] = {0}; + int ret = 0; + + (void *)data; /* ignore data */ + + if (message == 0) + { + fprintf( stderr, "Received message is null\n"); + g_logstorage_callback_return = -1; + 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, 1); + + /* payload contains "DLT_SERVICE_ID_OFFLINE_LOGSTORAGE, DLT_SERVICE_RESPONSE" as string + * that has to be checked */ + dlt_message_payload(message, text, DLT_RECEIVE_TEXTBUFSIZE,DLT_OUTPUT_ASCII, 1); + + ret = dlt_logstorage_analyze_response(text); + dlt_client_cleanup(&dltclient, 1); + + g_logstorage_callback_return = ret; + return ret; +} + +/* + * Communicate with daemon in a thread to detect communication errors (timeout). + */ +void *communicate_with_daemon (void *data) +{ + DltLogstorageCtrlData *ctrl = (DltLogstorageCtrlData *) data; + /* Initialize DLT Client */ + dlt_client_init(&dltclient, 1); + + /* Register callback to be called when message was received */ + dlt_client_register_message_callback(dlt_logstorage_message_callback); + + dltclient.servIP = "localhost"; + + /* Connect to TCP socket or open serial device */ + dlt_client_connect(&dltclient, 1); + + if (dlt_send_logstorage_request(dltclient.sock, ctrl->device_number, ctrl->connection_type, ctrl->ecuid) != 0) + { + fprintf(stderr, "dlt_send_logstorage_request failed. Exit.\n"); + } + else + { + /* Dlt Client Main Loop */ + dlt_client_main_loop(&dltclient, NULL, 1); + } + + return (void *)0; +} + +/* + * Resonse received in form of "service(<id>), <ok, error> + * check if id is DLT_SERVICE_ID_OFFLINE_LOGSTORAGE and return value either ok or error. + */ +int dlt_logstorage_analyze_response(char *data) +{ + int ret = 0; + char resp_ok[20] = {0}; + char resp_nok[20] = {0}; + + if (data == NULL) + return -1; + + snprintf(resp_ok, 20, "service(%u), ok", DLT_SERVICE_ID_OFFLINE_LOGSTORAGE); + snprintf(resp_nok, 20, "service(%u), error", DLT_SERVICE_ID_OFFLINE_LOGSTORAGE); + + if (strncmp(data, resp_ok, strlen(resp_ok)) == 0) + { + dlt_client_cleanup(&dltclient, 1); + ret = 0; + } + else if (strncmp(data, resp_nok, strlen(resp_nok)) == 0) + { + dlt_client_cleanup(&dltclient, 1); + ret = -1; + } + else + { + /* fall through */ + } + + g_logstorage_callback_return = ret; + return ret; +} + +int main(int argc, char *argv[]) +{ + DltLogstorageCtrlData ctrl_data; + pthread_t daemon_connect_thread; + int c = 0; + int ret = 0; + int timeout = DLT_LOGSTORAGE_CTRL_TIMEOUT; + struct timespec t; + + /* Initialize control data */ + memset(&ctrl_data, 0, sizeof(DltLogstorageCtrlData)); + + /* Get command line arguments */ + opterr = 0; + + while ((c = getopt(argc, argv, "t:he:d:c:")) != -1) + { + switch(c) + { + case 't': + timeout = (int) strtol(optarg,NULL, 10); + if (timeout <= 1) + { + fprintf(stderr, "Timeout to small. Set to default: %d", DLT_LOGSTORAGE_CTRL_TIMEOUT); + timeout = DLT_LOGSTORAGE_CTRL_TIMEOUT; + } + break; + case 'h': + usage(); + return -1; + case 'e': + strncpy(ctrl_data.ecuid, optarg, DLT_DAEMON_ECUID_LEN); + break; + case 'd': + ctrl_data.device_number = (int) strtol(optarg, NULL, 10); + break; + case 'c': + ctrl_data.connection_type = (int) strtol(optarg, NULL, 10); + break; + case '?': + if (optopt == 'c' || optopt == 'd' || optopt == 'e') + { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } + else if (isprint(optopt)) + { + fprintf(stderr, "Unknown option -%c.\n", optopt); + } + else + { + fprintf(stderr, "Unknown option character \\x%x.\n", optopt); + } + + usage(); + return -1; + default: + fprintf(stdout, "Try %s -h for more information.\n", argv[0]); + return -1; + } + } + + /* Check if device number and connection type configured correclty */ + if (ctrl_data.connection_type < 0 || ctrl_data.connection_type > 1) + { + fprintf(stderr, "Please check connection type parameter. Try %s -h for more information.\n", argv[0]); + return -1; + } + + if (ctrl_data.device_number <= 0) + { + fprintf(stderr, "Please check device parameter. Try %s -h for more information.\n", argv[0]); + return -1; + } + + /* Inside DLT Logstorage, devices are stored in an array. This starts with device 0 + * Therefore, we decrease given device number by 1 */ + ctrl_data.device_number -= 1; + + if (clock_gettime(CLOCK_REALTIME, &t) == -1) + { + fprintf(stderr, "Cannot read system time.\n"); + return -1; + } + + /* set timeout */ + t.tv_sec += timeout; + + /* Contact DLT daemon */ + if (pthread_create(&daemon_connect_thread, NULL, communicate_with_daemon, &ctrl_data) != 0) { + fprintf(stderr, "Cannot create thread to communicate with DLT daemon.\n"); + return -1; + } + + /* Wait for thread */ + ret = pthread_timedjoin_np(daemon_connect_thread, NULL, &t); + + if (ret != 0) + { + fprintf( stderr, "Connection to Dlt Daemon timed out.\n"); + fprintf( stderr, "Sending command to DLT daemon was not successful.\n"); + } + else + { + /* Check callback return value */ + if (g_logstorage_callback_return != 0) { + fprintf( stderr, "Sending command to DLT daemon was not successful.\n"); + ret = -1; + } + } + + return ret; +} |