3 * Copyright (C) 2012 BMW AG
5 * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
7 * Contributions are licensed to the GENIVI Alliance under one or more
8 * Contribution License Agreements.
11 * This Source Code Form is subject to the terms of the
12 * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
13 * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
16 * \author Alexander Wenzel <alexander.aw.wenzel@bmw.de> BMW 2011-2012
19 * For further information see http://www.genivi.org/.
24 /*******************************************************************************
26 ** SRC-MODULE: dlt_user.c **
32 ** AUTHOR : Alexander Wenzel Alexander.AW.Wenzel@bmw.de **
39 ** PLATFORM DEPENDANT [yes/no]: yes **
41 ** TO BE CHANGED BY USER [yes/no]: no **
43 *******************************************************************************/
45 /*******************************************************************************
47 ********************************************************************************
49 ** Initials Name Company **
50 ** -------- ------------------------- ---------------------------------- **
51 ** aw Alexander Wenzel BMW **
52 ** mk Markus Klein Fraunhofer ESK **
53 *******************************************************************************/
55 /*******************************************************************************
56 ** Revision Control History **
57 *******************************************************************************/
60 * $LastChangedRevision: 1670 $
61 * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $
66 #include <stdlib.h> /* for getenv(), free(), atexit() */
67 #include <string.h> /* for strcmp(), strncmp(), strlen(), memset(), memcpy() */
68 #include <signal.h> /* for signal(), SIGPIPE, SIG_IGN */
70 #if !defined (__WIN32__)
71 #include <syslog.h> /* for LOG_... */
72 #include <semaphore.h>
73 #include <pthread.h> /* POSIX Threads */
83 #include <sys/uio.h> /* writev() */
86 #include <sys/prctl.h>
89 #include "dlt_user_shared.h"
90 #include "dlt_user_shared_cfg.h"
91 #include "dlt_user_cfg.h"
93 static DltUser dlt_user;
94 static int dlt_user_initialised = 0;
95 static int dlt_user_freeing = 0;
97 static char str[DLT_USER_BUFFER_LENGTH];
99 static sem_t dlt_mutex;
100 static pthread_t dlt_receiverthread_handle;
101 static pthread_attr_t dlt_receiverthread_attr;
103 /* Segmented Network Trace */
104 #define DLT_MAX_TRACE_SEGMENT_SIZE 1024
105 #define DLT_MESSAGE_QUEUE_NAME "/dlt_message_queue"
106 #define DLT_DELAYED_RESEND_INDICATOR_PATTERN 0xFFFF
108 /* Mutex to wait on while message queue is not initialized */
109 pthread_mutex_t mq_mutex;
110 pthread_cond_t mq_init_condition;
112 /* Structure to pass data to segmented thread */
116 DltNetworkTraceType nw_trace_type;
119 uint16_t payload_len;
123 /* Function prototypes for internally used functions */
124 static void dlt_user_receiverthread_function(void *ptr);
125 static void dlt_user_atexit_handler(void);
126 static int dlt_user_log_init(DltContext *handle, DltContextData *log);
127 static DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype);
128 static int dlt_user_log_send_register_application(void);
129 static int dlt_user_log_send_unregister_application(void);
130 static int dlt_user_log_send_register_context(DltContextData *log);
131 static int dlt_user_log_send_unregister_context(DltContextData *log);
132 static int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus);
133 static int dlt_user_log_send_log_mode(DltUserLogMode mode);
134 static int dlt_user_print_msg(DltMessage *msg, DltContextData *log);
135 static int dlt_user_log_check_user_message(void);
136 static void dlt_user_log_reattach_to_daemon(void);
137 static int dlt_user_log_send_overflow(void);
138 static void dlt_user_trace_network_segmented_thread(void *unused);
139 static void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data);
140 static int dlt_user_queue_resend(void);
142 int dlt_user_check_library_version(const char *user_major_version,const char *user_minor_version){
145 char lib_major_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
146 char lib_minor_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
148 dlt_get_major_version( lib_major_version);
149 dlt_get_minor_version( lib_minor_version);
151 if( (strcmp(lib_major_version,user_major_version)!=0) || (strcmp(lib_minor_version,user_minor_version)!=0))
153 sprintf(str,"DLT Library version check failed! Installed DLT library version is %s.%s - Application using DLT library version %s.%s\n",lib_major_version,lib_minor_version,user_major_version,user_minor_version);
154 dlt_log(LOG_WARNING, str);
162 char filename[DLT_USER_MAX_FILENAME_LENGTH];
165 // process is exiting. Do not allocate new resources.
166 if (dlt_user_freeing != 0)
168 // return negative value, to stop the current log
172 // WARNING: multithread unsafe !
173 // Another thread will check that dlt_user_initialised != 0, but the lib is not initialised !
174 dlt_user_initialised = 1;
176 /* Initialize common part of dlt_init()/dlt_init_file() */
177 if (dlt_init_common()==-1)
179 dlt_user_initialised = 0;
183 /* check environment variables */
186 dlt_user.dlt_is_file = 0;
187 dlt_user.overflow = 0;
188 dlt_user.overflow_counter = 0;
189 #ifdef DLT_SHM_ENABLE
190 memset(&(dlt_user.dlt_shm),0,sizeof(DltShm));
193 /* create and open DLT user FIFO */
194 sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
196 /* Try to delete existing pipe, ignore result of unlink */
199 ret=mkfifo(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP );
202 sprintf(str,"Loging disabled, FIFO user %s cannot be created!\n",filename);
203 dlt_log(LOG_WARNING, str);
204 /* return 0; */ /* removed to prevent error, when FIFO already exists */
207 // S_IWGRP cannot be set by mkfifo (???), let's reassign right bits
208 ret=chmod(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP );
211 sprintf(str,"FIFO user %s cannot be chmoded!\n", DLT_USER_DIR);
212 dlt_log(LOG_ERR, str);
216 dlt_user.dlt_user_handle = open(filename, O_RDWR | O_CLOEXEC);
217 if (dlt_user.dlt_user_handle == DLT_FD_INIT)
219 sprintf(str,"Loging disabled, FIFO user %s cannot be opened!\n",filename);
220 dlt_log(LOG_WARNING, str);
225 /* open DLT output FIFO */
226 dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK | O_CLOEXEC );
227 if (dlt_user.dlt_log_handle==-1)
229 sprintf(str,"Loging disabled, FIFO %s cannot be opened with open()!\n",DLT_USER_FIFO);
230 dlt_log(LOG_WARNING, str);
235 #ifdef DLT_SHM_ENABLE
236 /* init shared memory */
237 if (dlt_shm_init_client(&(dlt_user.dlt_shm),DLT_SHM_KEY) < 0)
239 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
240 dlt_log(LOG_WARNING, str);
247 if (dlt_receiver_init(&(dlt_user.receiver),dlt_user.dlt_user_handle, DLT_USER_RCVBUF_MAX_SIZE)==-1)
249 dlt_user_initialised = 0;
253 /* Start receiver thread */
254 if (pthread_create(&(dlt_receiverthread_handle),
256 (void *) &dlt_user_receiverthread_function,
259 if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
261 dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
264 dlt_log(LOG_CRIT, "Can't create receiver thread!\n");
265 dlt_user_initialised = 0;
269 if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
271 dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
274 /* These will be lazy initialized only when needed */
275 dlt_user.dlt_segmented_queue_read_handle = -1;
276 dlt_user.dlt_segmented_queue_write_handle = -1;
278 /* Wait mutext for segmented thread */
279 pthread_mutex_init(&mq_mutex, NULL);
280 pthread_cond_init(&mq_init_condition, NULL);
282 /* Start the segmented thread */
283 if(pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL,
284 (void *)dlt_user_trace_network_segmented_thread, NULL))
286 dlt_log(LOG_CRIT, "Can't start segmented thread!\n");
293 int dlt_init_file(const char *name)
295 dlt_user_initialised = 1;
297 /* Initialize common part of dlt_init()/dlt_init_file() */
298 if (dlt_init_common()==-1)
300 dlt_user_initialised = 0;
304 dlt_user.dlt_is_file = 1;
306 /* open DLT output file */
307 dlt_user.dlt_log_handle = open(name,O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
308 if (dlt_user.dlt_log_handle == -1)
310 sprintf(str,"Log file %s cannot be opened!\n",name);
311 dlt_log(LOG_ERR, str);
318 int dlt_init_message_queue(void)
320 pthread_mutex_lock(&mq_mutex);
321 if(dlt_user.dlt_segmented_queue_read_handle >= 0 &&
322 dlt_user.dlt_segmented_queue_write_handle >= 0)
324 // Already intialized
325 pthread_mutex_unlock(&mq_mutex);
329 /* Generate per process name for queue */
330 char queue_name[NAME_MAX];
331 sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
333 /* Maximum queue size is 10, limit to size of pointers */
334 struct mq_attr mqatr;
336 mqatr.mq_maxmsg = 10;
337 mqatr.mq_msgsize = sizeof(s_segmented_data *);
338 mqatr.mq_curmsgs = 0;
341 * Create the message queue. It must be newly created
342 * if old one was left by a crashing process.
344 dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
345 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
346 if(dlt_user.dlt_segmented_queue_read_handle < 0)
350 dlt_log(LOG_WARNING, "Old message queue exists, trying to delete.\n");
351 if(mq_unlink(queue_name) < 0)
354 snprintf(str,255,"Could not delete existing message queue!: %s \n",strerror(errno));
355 dlt_log(LOG_CRIT, str);
359 dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
360 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
363 if(dlt_user.dlt_segmented_queue_read_handle < 0)
366 snprintf(str,255,"Can't create message queue read handle!: %s \n",strerror(errno));
367 dlt_log(LOG_CRIT, str);
368 pthread_mutex_unlock(&mq_mutex);
373 dlt_user.dlt_segmented_queue_write_handle = mq_open(queue_name, O_WRONLY|O_NONBLOCK);
374 if(dlt_user.dlt_segmented_queue_write_handle < 0)
378 snprintf(str,255,"Can't open message queue write handle!: %s \n",strerror(errno));
379 dlt_log(LOG_CRIT, str);
380 pthread_mutex_unlock(&mq_mutex);
384 pthread_cond_signal(&mq_init_condition);
385 pthread_mutex_unlock(&mq_mutex);
389 int dlt_init_common(void)
391 char *env_local_print;
393 /* Binary semaphore for threads */
394 if (sem_init(&dlt_mutex, 0, 1)==-1)
396 dlt_user_initialised = 0;
400 /* set to unknown state of connected client */
401 dlt_user.log_state = -1;
403 dlt_user.dlt_log_handle=-1;
404 dlt_user.dlt_user_handle=DLT_FD_INIT;
406 dlt_set_id(dlt_user.ecuID,DLT_USER_DEFAULT_ECU_ID);
407 dlt_set_id(dlt_user.appID,"");
409 dlt_user.application_description = 0;
411 /* Verbose mode is enabled by default */
412 dlt_user.verbose_mode = 1;
414 /* Local print is disabled by default */
415 dlt_user.enable_local_print = 0;
417 dlt_user.local_print_mode = DLT_PM_UNSET;
419 env_local_print = getenv(DLT_USER_ENV_LOCAL_PRINT_MODE);
422 if (strcmp(env_local_print,"AUTOMATIC")==0)
424 dlt_user.local_print_mode = DLT_PM_AUTOMATIC;
426 else if (strcmp(env_local_print,"FORCE_ON")==0)
428 dlt_user.local_print_mode = DLT_PM_FORCE_ON;
430 else if (strcmp(env_local_print,"FORCE_OFF")==0)
432 dlt_user.local_print_mode = DLT_PM_FORCE_OFF;
436 /* Initialize LogLevel/TraceStatus field */
438 dlt_user.dlt_ll_ts = 0;
439 dlt_user.dlt_ll_ts_max_num_entries = 0;
440 dlt_user.dlt_ll_ts_num_entries = 0;
442 if (dlt_buffer_init_dynamic(&(dlt_user.startup_buffer), DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)==-1)
444 dlt_user_initialised = 0;
450 signal(SIGPIPE,SIG_IGN); /* ignore pipe signals */
452 atexit(dlt_user_atexit_handler);
454 #ifdef DLT_TEST_ENABLE
455 dlt_user.corrupt_user_header = 0;
456 dlt_user.corrupt_message_size = 0;
457 dlt_user.corrupt_message_size_size = 0;
463 void dlt_user_atexit_handler(void)
465 if (dlt_user_initialised==0)
467 dlt_log(LOG_WARNING, "dlt_user_atexit_handler dlt_user_initialised==0\n");
473 /* Try to resend potential log messages in the user buffer */
474 int count = dlt_user_atexit_blow_out_user_buffer();
478 sprintf(tmp,"Lost log messages in user buffer when exiting: %i\n",count);
479 dlt_log(LOG_ERR, tmp);
482 /* Unregister app (this also unregisters all contexts in daemon) */
483 /* Ignore return value */
484 dlt_unregister_app();
487 /* Ignore return value */
491 int dlt_user_atexit_blow_out_user_buffer(void){
495 uint32_t exitTime = dlt_uptime() + DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT;
497 while(dlt_uptime() < exitTime ){
499 ret = dlt_user_log_resend_buffer();
506 usleep(DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP);
510 count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
519 char filename[DLT_USER_MAX_FILENAME_LENGTH];
521 if( dlt_user_freeing != 0 )
522 // resources are already being freed. Do nothing and return.
525 // library is freeing its resources. Avoid to allocate it in dlt_init()
526 dlt_user_freeing = 1;
528 if (dlt_user_initialised==0)
530 dlt_user_freeing = 0;
533 dlt_user_initialised = 0;
535 if (dlt_receiverthread_handle)
537 /* Ignore return value */
538 pthread_cancel(dlt_receiverthread_handle);
541 if (dlt_user.dlt_segmented_nwt_handle)
543 pthread_cancel(dlt_user.dlt_segmented_nwt_handle);
546 if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
548 sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
550 close(dlt_user.dlt_user_handle);
551 dlt_user.dlt_user_handle=DLT_FD_INIT;
556 #ifdef DLT_SHM_ENABLE
557 /* free shared memory */
558 dlt_shm_free_client(&dlt_user.dlt_shm);
561 if (dlt_user.dlt_log_handle!=-1)
563 /* close log file/output fifo to daemon */
564 close(dlt_user.dlt_log_handle);
565 dlt_user.dlt_log_handle = -1;
568 /* Ignore return value */
570 dlt_receiver_free(&(dlt_user.receiver));
573 /* Ignore return value */
575 dlt_buffer_free_dynamic(&(dlt_user.startup_buffer));
579 if (dlt_user.dlt_ll_ts)
581 for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
583 if (dlt_user.dlt_ll_ts[i].injection_table!=0)
585 free(dlt_user.dlt_ll_ts[i].injection_table);
586 dlt_user.dlt_ll_ts[i].injection_table = 0;
588 dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
591 free(dlt_user.dlt_ll_ts);
592 dlt_user.dlt_ll_ts = 0;
593 dlt_user.dlt_ll_ts_max_num_entries = 0;
594 dlt_user.dlt_ll_ts_num_entries = 0;
598 char queue_name[NAME_MAX];
599 sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
602 * Ignore errors from these, to not to spam user if dlt_free
603 * is accidentally called multiple times.
605 mq_close(dlt_user.dlt_segmented_queue_write_handle);
606 mq_close(dlt_user.dlt_segmented_queue_read_handle);
607 mq_unlink(queue_name);
609 // allow the user app to do dlt_init() again.
610 // The flag is unset only to keep almost the same behaviour as before, on EntryNav
611 // This should be removed for other projects (see documentation of dlt_free()
612 dlt_user_freeing = 0;
617 int dlt_check_library_version(const char * user_major_version,const char * user_minor_version)
619 return dlt_user_check_library_version(user_major_version, user_minor_version);
622 int dlt_register_app(const char *appid, const char * description)
626 if (dlt_user_initialised==0)
634 if ((appid==0) || (appid[0]=='\0'))
639 /* check if application already registered */
640 /* if yes do not register again */
643 if(appid[0]==dlt_user.appID[0])
648 if(appid[0]==dlt_user.appID[0] &&
649 appid[1]==dlt_user.appID[1])
654 if(appid[0]==dlt_user.appID[0] &&
655 appid[1]==dlt_user.appID[1] &&
656 appid[2]==dlt_user.appID[2])
661 if(appid[0]==dlt_user.appID[0] &&
662 appid[1]==dlt_user.appID[1] &&
663 appid[2]==dlt_user.appID[2] &&
664 appid[3]==dlt_user.appID[3])
670 /* Store locally application id and application description */
671 dlt_set_id(dlt_user.appID, appid);
673 if (dlt_user.application_description!=0)
675 free(dlt_user.application_description);
678 dlt_user.application_description = 0;
682 size_t desc_len = strlen(description);
683 dlt_user.application_description= malloc(desc_len+1);
684 if (dlt_user.application_description){
685 strncpy(dlt_user.application_description, description, desc_len);
687 /* Terminate transmitted string with 0 */
688 dlt_user.application_description[desc_len]='\0';
699 ret = dlt_user_log_send_register_application();
703 int dlt_register_context(DltContext *handle, const char *contextid, const char * description)
705 if (dlt_user_initialised==0)
715 if (dlt_user.appID[0]=='\0')
717 dlt_log(LOG_ERR, "no application registered!\n");
723 if ((contextid==0) || (contextid[0]=='\0'))
731 return dlt_register_context_ll_ts(handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET);
734 int dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const char * description, int loglevel, int tracestatus)
739 char ctid[DLT_ID_SIZE+1];
741 if (dlt_user_initialised==0)
751 if (dlt_user.appID[0]=='\0')
753 dlt_log(LOG_ERR, "no application registered!\n");
761 if ((contextid==0) || (contextid[0]=='\0'))
766 if ((loglevel<DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel>DLT_LOG_VERBOSE) || (loglevel==DLT_LOG_DEFAULT))
771 if ((tracestatus<DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus>DLT_TRACE_STATUS_ON) || (tracestatus==DLT_TRACE_STATUS_DEFAULT))
776 if (dlt_user_log_init(handle, &log)==-1)
781 /* Reset message counter */
784 /* Store context id in log level/trace status field */
786 /* Check if already registered, else register context */
790 for (i=0;i<dlt_user.dlt_ll_ts_num_entries;i++)
792 if (dlt_user.dlt_ll_ts)
794 if (memcmp(dlt_user.dlt_ll_ts[i].contextID, contextid,DLT_ID_SIZE)==0)
798 memset(ctid,0,(DLT_ID_SIZE+1));
799 dlt_print_id(ctid, contextid);
801 sprintf(str,"context '%s' already registered!\n",ctid);
802 dlt_log(LOG_WARNING, str);
811 /* Allocate or expand context array */
812 if (dlt_user.dlt_ll_ts == 0)
814 dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*DLT_USER_CONTEXT_ALLOC_SIZE);
815 if (dlt_user.dlt_ll_ts==0)
821 dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE;
823 /* Initialize new entries */
824 for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
826 dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
828 /* At startup, logging and tracing is locally enabled */
829 /* the correct log level/status is set after received from daemon */
830 dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
831 dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
833 dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
834 dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
836 dlt_user.dlt_ll_ts[i].context_description = 0;
838 dlt_user.dlt_ll_ts[i].injection_table = 0;
839 dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
844 if ((dlt_user.dlt_ll_ts_num_entries%DLT_USER_CONTEXT_ALLOC_SIZE)==0)
846 /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
847 dlt_ll_ts_type *old_ll_ts;
848 uint32_t old_max_entries;
850 old_ll_ts = dlt_user.dlt_ll_ts;
851 old_max_entries = dlt_user.dlt_ll_ts_max_num_entries;
853 dlt_user.dlt_ll_ts_max_num_entries = ((dlt_user.dlt_ll_ts_num_entries/DLT_USER_CONTEXT_ALLOC_SIZE)+1)*DLT_USER_CONTEXT_ALLOC_SIZE;
854 dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*
855 dlt_user.dlt_ll_ts_max_num_entries);
856 if (dlt_user.dlt_ll_ts==0)
858 dlt_user.dlt_ll_ts = old_ll_ts;
859 dlt_user.dlt_ll_ts_max_num_entries = old_max_entries;
864 memcpy(dlt_user.dlt_ll_ts,old_ll_ts,sizeof(dlt_ll_ts_type)*dlt_user.dlt_ll_ts_num_entries);
867 /* Initialize new entries */
868 for (i=dlt_user.dlt_ll_ts_num_entries;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
870 dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
872 /* At startup, logging and tracing is locally enabled */
873 /* the correct log level/status is set after received from daemon */
874 dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
875 dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
877 dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
878 dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
880 dlt_user.dlt_ll_ts[i].context_description = 0;
882 dlt_user.dlt_ll_ts[i].injection_table = 0;
883 dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
888 /* Store locally context id and context description */
889 dlt_set_id(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].contextID, contextid);
891 if (dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description!=0)
893 free(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description);
896 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = 0;
900 size_t desc_len = strlen(description);
901 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = malloc(desc_len+1);
902 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description == 0)
908 strncpy(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description, description, desc_len);
910 /* Terminate transmitted string with 0 */
911 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description[desc_len]='\0';
914 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
916 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr = malloc(sizeof(int8_t));
917 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
923 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
925 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr = malloc(sizeof(int8_t));
926 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
933 if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
935 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = loglevel;
938 if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
940 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
943 /* Prepare transfer struct */
944 //dlt_set_id(log->appID, dlt_user.appID);
945 dlt_set_id(handle->contextID, contextid);
946 handle->log_level_pos = dlt_user.dlt_ll_ts_num_entries;
948 handle->log_level_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr;
949 handle->trace_status_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr;
951 log.context_description = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description;
953 *(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr) = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level;
954 *(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr) = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
956 if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
958 log.log_level = loglevel;
962 log.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
965 if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
967 log.trace_status = tracestatus;
971 log.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
974 dlt_user.dlt_ll_ts_num_entries++;
978 ret=dlt_user_log_send_register_context(&log);
990 int dlt_unregister_app(void)
994 if (dlt_user_initialised==0)
999 /* Inform daemon to unregister application and all of its contexts */
1000 ret = dlt_user_log_send_unregister_application();
1004 /* Clear and free local stored application information */
1005 dlt_set_id(dlt_user.appID, "");
1007 if (dlt_user.application_description!=0)
1009 free(dlt_user.application_description);
1012 dlt_user.application_description = 0;
1019 int dlt_unregister_context(DltContext *handle)
1024 if (dlt_user_initialised==0)
1029 if (dlt_user_log_init(handle, &log) == -1)
1036 handle->log_level_ptr = 0;
1037 handle->trace_status_ptr = 0;
1039 if (dlt_user.dlt_ll_ts)
1041 /* Clear and free local stored context information */
1042 dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, "");
1044 dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
1045 dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
1047 if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description!=0)
1049 free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
1052 if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr!=0)
1054 free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr);
1055 dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = 0;
1058 if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr!=0)
1060 free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr);
1061 dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = 0;
1064 dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = 0;
1066 if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table)
1068 free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
1069 dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = 0;
1072 dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks = 0;
1077 /* Inform daemon to unregister context */
1078 ret = dlt_user_log_send_unregister_context(&log);
1083 int dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus)
1088 if (dlt_user_initialised==0)
1096 /* Removed because of DltLogLevelType and DltTraceStatusType
1098 if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
1103 if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
1108 if (dlt_user.dlt_ll_ts==0)
1116 if (dlt_user.dlt_ll_ts==0)
1122 /* Update local structures */
1123 for (i=0; i<dlt_user.dlt_ll_ts_num_entries;i++)
1125 dlt_user.dlt_ll_ts[i].log_level = loglevel;
1126 dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
1127 if(dlt_user.dlt_ll_ts[i].log_level_ptr)
1128 *(dlt_user.dlt_ll_ts[i].log_level_ptr) = loglevel;
1129 if(dlt_user.dlt_ll_ts[i].trace_status_ptr)
1130 *(dlt_user.dlt_ll_ts[i].trace_status_ptr) = tracestatus;
1135 /* Inform DLT server about update */
1136 ret = dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus);
1141 int dlt_get_log_state()
1143 return dlt_user.log_state;
1146 int dlt_set_log_mode(DltUserLogMode mode)
1148 if (dlt_user_initialised==0)
1156 return dlt_user_log_send_log_mode(mode);
1159 int dlt_forward_msg(void *msgdata,size_t size)
1161 DltUserHeader userheader;
1164 if ((msgdata==0) || (size==0))
1169 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
1171 /* Type of internal user message; same value for Trace messages */
1175 if (dlt_user.dlt_is_file)
1178 ret = dlt_user_log_out2(dlt_user.dlt_log_handle, msgdata, size, 0, 0);
1179 return ((ret==DLT_RETURN_OK)?0:-1);
1183 /* Reattach to daemon if neccesary */
1184 dlt_user_log_reattach_to_daemon();
1186 if (dlt_user.overflow_counter)
1188 if (dlt_user_log_send_overflow()==0)
1190 sprintf(str,"Buffer full! %u messages discarded!\n",dlt_user.overflow_counter);
1191 dlt_log(LOG_ERR, str);
1192 dlt_user.overflow_counter=0; }
1196 ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
1197 &(userheader), sizeof(DltUserHeader),
1198 msgdata, size, 0, 0);
1200 /* store message in ringbuffer, if an error has occured */
1201 if (ret!=DLT_RETURN_OK)
1205 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
1206 (unsigned char *)&(userheader), sizeof(DltUserHeader),
1207 msgdata, size, 0, 0)==-1)
1209 if(dlt_user.overflow_counter==0)
1211 dlt_log(LOG_ERR,"Buffer full! First message discarded!\n");
1213 ret = DLT_RETURN_BUFFER_FULL;
1218 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
1220 ;//dlt_log(LOG_WARNING, "dlt_forward_msg: Failed to queue resending.\n");
1226 case DLT_RETURN_BUFFER_FULL:
1229 dlt_user.overflow_counter += 1;
1232 case DLT_RETURN_PIPE_FULL:
1234 /* data could not be written */
1237 case DLT_RETURN_PIPE_ERROR:
1239 /* handle not open or pipe error */
1240 close(dlt_user.dlt_log_handle);
1241 dlt_user.dlt_log_handle = -1;
1245 case DLT_RETURN_ERROR:
1247 /* other error condition */
1256 /* This case should not occur */
1265 /* ********************************************************************************************* */
1267 inline int dlt_user_log_write_start(DltContext *handle, DltContextData *log,DltLogLevelType loglevel)
1269 return dlt_user_log_write_start_id(handle,log,loglevel,DLT_USER_DEFAULT_MSGID);
1272 int dlt_user_log_write_start_id(DltContext *handle, DltContextData *log,DltLogLevelType loglevel, uint32_t messageid)
1274 if(dlt_user_initialised==0)
1286 if (dlt_user_log_init(handle, log)==-1)
1291 if (dlt_user.dlt_ll_ts==0)
1296 if (handle->log_level_ptr && (loglevel<=(int)*(handle->log_level_ptr) ) && (loglevel!=0))
1299 log->log_level = loglevel;
1301 /* In non-verbose mode, insert message id */
1302 if (dlt_user.verbose_mode==0)
1304 if ((sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1308 /* Write message id */
1309 memcpy(log->buffer,&(messageid),sizeof(uint32_t));
1310 log->size = sizeof(uint32_t);
1312 /* as the message id is part of each message in non-verbose mode,
1313 it doesn't increment the argument counter in extended header (if used) */
1322 int dlt_user_log_write_finish(DltContextData *log)
1329 return dlt_user_log_send_log(log, DLT_TYPE_LOG) < 0 ? -1 : 0;
1332 int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length)
1342 if ((log->size+length+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1347 if (dlt_user.verbose_mode)
1349 if ((log->size+length+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1354 /* Transmit type information */
1355 type_info = DLT_TYPE_INFO_RAWD;
1357 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1358 log->size += sizeof(uint32_t);
1362 /* First transmit length of raw data, then the raw data itself */
1363 arg_size = (uint16_t)length;
1365 memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1366 log->size += sizeof(uint16_t);
1368 memcpy((log->buffer)+log->size,data,arg_size);
1369 log->size += arg_size;
1376 int dlt_user_log_write_float32(DltContextData *log, float32_t data)
1385 if (sizeof(float32_t)!=4)
1390 if ((log->size+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1395 if (dlt_user.verbose_mode)
1397 if ((log->size+sizeof(uint32_t)+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1402 type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
1404 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1405 log->size += sizeof(uint32_t);
1408 memcpy((log->buffer)+log->size,&data, sizeof(float32_t));
1409 log->size += sizeof(float32_t);
1416 int dlt_user_log_write_float64(DltContextData *log, float64_t data)
1425 if (sizeof(float64_t)!=8)
1430 if ((log->size+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1435 if (dlt_user.verbose_mode)
1437 if ((log->size+sizeof(uint32_t)+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1442 type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
1444 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1445 log->size += sizeof(uint32_t);
1448 memcpy((log->buffer)+log->size,&data, sizeof(float64_t));
1449 log->size += sizeof(float64_t);
1456 int dlt_user_log_write_uint( DltContextData *log, unsigned int data)
1463 switch (sizeof(unsigned int))
1467 return dlt_user_log_write_uint8(log, (uint8_t)data);
1472 return dlt_user_log_write_uint16(log, (uint16_t)data);
1477 return dlt_user_log_write_uint32(log, (uint32_t)data);
1482 return dlt_user_log_write_uint64(log, (uint64_t)data);
1495 int dlt_user_log_write_uint8(DltContextData *log, uint8_t data)
1504 if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1509 if (dlt_user.verbose_mode)
1511 if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1516 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
1518 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1519 log->size += sizeof(uint32_t);
1522 memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1523 log->size += sizeof(uint8_t);
1530 int dlt_user_log_write_uint16(DltContextData *log, uint16_t data)
1539 if ((log->size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1544 if (dlt_user.verbose_mode)
1546 if ((log->size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1551 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
1553 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1554 log->size += sizeof(uint32_t);
1557 memcpy((log->buffer)+log->size,&data,sizeof(uint16_t));
1558 log->size += sizeof(uint16_t);
1565 int dlt_user_log_write_uint32(DltContextData *log, uint32_t data)
1574 if ((log->size+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1579 if (dlt_user.verbose_mode)
1581 if ((log->size+sizeof(uint32_t)+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1586 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
1588 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1589 log->size += sizeof(uint32_t);
1592 memcpy((log->buffer)+log->size,&data, sizeof(uint32_t));
1593 log->size += sizeof(uint32_t);
1600 int dlt_user_log_write_uint64(DltContextData *log, uint64_t data)
1609 if ((log->size+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1614 if (dlt_user.verbose_mode)
1616 if ((log->size+sizeof(uint32_t)+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1621 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
1623 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1624 log->size +=sizeof(uint32_t);
1627 memcpy((log->buffer)+log->size,&data,sizeof(uint64_t));
1628 log->size += sizeof(uint64_t);
1635 int dlt_user_log_write_int(DltContextData *log, int data)
1642 switch (sizeof(int))
1646 return dlt_user_log_write_int8(log, (int8_t)data);
1651 return dlt_user_log_write_int16(log, (int16_t)data);
1656 return dlt_user_log_write_int32(log, (int32_t)data);
1661 return dlt_user_log_write_int64(log, (int64_t)data);
1674 int dlt_user_log_write_int8(DltContextData *log, int8_t data)
1683 if ((log->size+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1688 if (dlt_user.verbose_mode)
1690 if ((log->size+sizeof(uint32_t)+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1695 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
1697 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1698 log->size += sizeof(uint32_t);
1701 memcpy((log->buffer)+log->size,&data,sizeof(int8_t));
1702 log->size += sizeof(int8_t);
1709 int dlt_user_log_write_int16(DltContextData *log, int16_t data)
1718 if ((log->size+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1723 if (dlt_user.verbose_mode)
1725 if ((log->size+sizeof(uint32_t)+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1730 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
1732 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1733 log->size += sizeof(uint32_t);
1736 memcpy((log->buffer)+log->size,&data,sizeof(int16_t));
1737 log->size += sizeof(int16_t);
1744 int dlt_user_log_write_int32(DltContextData *log, int32_t data)
1753 if ((log->size+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1758 if (dlt_user.verbose_mode)
1760 if ((log->size+sizeof(uint32_t)+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1765 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
1767 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1768 log->size += sizeof(uint32_t);
1771 memcpy((log->buffer)+log->size,&data, sizeof(int32_t));
1772 log->size += sizeof(int32_t);
1779 int dlt_user_log_write_int64(DltContextData *log, int64_t data)
1788 if ((log->size+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1793 if (dlt_user.verbose_mode)
1795 if ((log->size+sizeof(uint32_t)+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1800 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
1802 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1803 log->size += sizeof(uint32_t);
1806 memcpy((log->buffer)+log->size,&data,sizeof(int64_t));
1807 log->size += sizeof(int64_t);
1814 int dlt_user_log_write_bool(DltContextData *log, uint8_t data)
1823 if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1828 if (dlt_user.verbose_mode)
1830 if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1835 type_info = DLT_TYPE_INFO_BOOL;
1837 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1838 log->size += sizeof(uint32_t);
1841 memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1842 log->size += sizeof(uint8_t);
1849 int dlt_user_log_write_string(DltContextData *log, const char *text)
1854 if ((log==0) || (text==0))
1859 if ((log->size+(strlen(text)+1)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1864 if (dlt_user.verbose_mode)
1866 if ((log->size+(strlen(text)+1)+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1871 type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII;
1873 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1874 log->size += sizeof(uint32_t);
1877 arg_size = strlen(text) + 1;
1879 memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1880 log->size += sizeof(uint16_t);
1882 memcpy((log->buffer)+log->size,text,arg_size);
1883 log->size += arg_size;
1890 int dlt_user_log_write_utf8_string(DltContextData *log, const char *text)
1895 if ((log==0) || (text==0))
1900 arg_size = strlen(text)+1;
1902 if ((log->size+arg_size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1907 if (dlt_user.verbose_mode)
1909 if ((log->size+arg_size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1914 type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8;
1916 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1917 log->size += sizeof(uint32_t);
1920 arg_size = strlen(text) + 1;
1922 memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1923 log->size += sizeof(uint16_t);
1925 memcpy((log->buffer)+log->size,text,arg_size);
1926 log->size += arg_size;
1933 int dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
1934 int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length))
1940 DltUserInjectionCallback *old;
1947 if (dlt_user_log_init(handle, &log)==-1)
1952 if (service_id<DLT_USER_INJECTION_MIN)
1956 /* This function doesn't make sense storing to local file is choosen;
1957 so terminate this function */
1958 if (dlt_user.dlt_is_file)
1965 if (dlt_user.dlt_ll_ts==0)
1971 /* Insert callback in corresponding table */
1972 i=handle->log_level_pos;
1974 /* Insert each service_id only once */
1975 for (k=0;k<dlt_user.dlt_ll_ts[i].nrcallbacks;k++)
1977 if ((dlt_user.dlt_ll_ts[i].injection_table) &&
1978 (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id))
1991 j=dlt_user.dlt_ll_ts[i].nrcallbacks;
1993 /* Allocate or expand injection table */
1994 if (dlt_user.dlt_ll_ts[i].injection_table == 0)
1996 dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback));
1997 if(dlt_user.dlt_ll_ts[i].injection_table == 0)
2005 old = dlt_user.dlt_ll_ts[i].injection_table;
2006 dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback)*(j+1));
2007 if(dlt_user.dlt_ll_ts[i].injection_table == 0)
2009 dlt_user.dlt_ll_ts[i].injection_table = old;
2013 memcpy(dlt_user.dlt_ll_ts[i].injection_table,old,sizeof(DltUserInjectionCallback)*j);
2017 dlt_user.dlt_ll_ts[i].nrcallbacks++;
2020 /* Store service_id and corresponding function pointer for callback function */
2021 dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id;
2022 dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = dlt_injection_callback;
2035 int total_size, used_size;
2036 dlt_user_check_buffer(&total_size, &used_size);
2038 if((total_size - used_size) < (total_size/2))
2046 * Send the start of a segment chain.
2047 * Returns -1 on failure
2049 int dlt_user_trace_network_segmented_start(uint16_t *id, DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len)
2060 if (dlt_user_log_init(handle, &log)==-1)
2066 if (dlt_user.dlt_ll_ts==0)
2071 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2075 log.trace_status = nw_trace_type;
2078 gettimeofday(&tv, NULL);
2081 /* Write identifier */
2082 if(dlt_user_log_write_string(&log, "NWST") < 0)
2087 /* Write stream handle */
2088 if(dlt_user_log_write_uint16(&log, *id) < 0)
2094 if(dlt_user_log_write_raw(&log, header, header_len) < 0)
2099 /* Write size of payload */
2100 if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2105 /* Write expected segment count */
2106 uint16_t segment_count = payload_len/DLT_MAX_TRACE_SEGMENT_SIZE+1;
2108 /* If segments align perfectly with segment size, avoid sending empty segment */
2109 if((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0)
2114 if(dlt_user_log_write_uint16(&log, segment_count) < 0)
2119 /* Write length of one segment */
2120 if(dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0)
2126 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2131 int dlt_user_trace_network_segmented_segment(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
2133 while(check_buffer() < 0)
2135 usleep(1000*50); // Wait 50ms
2136 dlt_user_log_resend_buffer();
2146 if (dlt_user_log_init(handle, &log)==-1)
2151 if (dlt_user.dlt_ll_ts==0)
2156 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2160 log.trace_status = nw_trace_type;
2163 /* Write identifier */
2164 if(dlt_user_log_write_string(&log, "NWCH") < 0)
2169 /* Write stream handle */
2170 if(dlt_user_log_write_uint16(&log, id) < 0)
2175 /* Write segment sequence number */
2176 if(dlt_user_log_write_uint16(&log, sequence) < 0)
2182 if(dlt_user_log_write_raw(&log, payload, payload_len) < 0)
2188 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2191 /* Allow other threads to log between chunks */
2196 int dlt_user_trace_network_segmented_end(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type)
2205 if (dlt_user_log_init(handle, &log)==-1)
2212 if (dlt_user.dlt_ll_ts==0)
2217 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2221 log.trace_status = nw_trace_type;
2224 /* Write identifier */
2225 if(dlt_user_log_write_string(&log, "NWEN") < 0)
2230 /* Write stream handle */
2231 if(dlt_user_log_write_uint(&log, id) < 0)
2237 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2243 void dlt_user_trace_network_segmented_thread(void *unused)
2245 /* Unused on purpose. */
2248 prctl(PR_SET_NAME, "dlt_segmented", 0, 0, 0);
2250 s_segmented_data *data;
2254 // Wait until message queue is initialized
2255 pthread_mutex_lock(&mq_mutex);
2256 if(dlt_user.dlt_segmented_queue_read_handle < 0)
2258 pthread_cond_wait(&mq_init_condition, &mq_mutex);
2260 pthread_mutex_unlock(&mq_mutex);
2262 ssize_t read = mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char *)&data,
2263 sizeof(s_segmented_data * ), NULL);
2265 if(read != sizeof(s_segmented_data *))
2269 snprintf(str,254,"NWTSegmented: Error while reading queue: %s \n",strerror(errno));
2270 dlt_log(LOG_CRIT, str);
2274 /* Indicator just to try to flush the buffer */
2275 if(data->payload_len == DLT_DELAYED_RESEND_INDICATOR_PATTERN)
2277 // Sleep 100ms, to allow other process to read FIFO
2279 if(dlt_user_log_resend_buffer() < 0)
2281 // Requeue if still not empty
2282 if ( dlt_user_queue_resend() < 0 )
2284 //dlt_log(LOG_WARNING, "Failed to queue resending in dlt_user_trace_network_segmented_thread.\n");
2291 dlt_user_trace_network_segmented_thread_segmenter(data);
2293 /* Send the end message */
2294 DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type);
2295 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2297 dlt_log(LOG_ERR,"NWTSegmented: Could not send end segment.\n");
2300 /* Free resources */
2302 free(data->payload);
2307 void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data)
2309 /* Segment the data and send the chunks */
2311 uint16_t offset = 0;
2312 uint16_t sequence = 0;
2316 if(offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len)
2318 len = data->payload_len - offset;
2322 len = DLT_MAX_TRACE_SEGMENT_SIZE;
2324 /* If payload size aligns perfectly with segment size, avoid sending empty segment */
2330 ptr = data->payload + offset;
2331 DltReturnValue err = dlt_user_trace_network_segmented_segment(data->id, data->handle, data->nw_trace_type, sequence++, len, ptr);
2332 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2334 dlt_log(LOG_ERR,"NWTSegmented: Could not send segment. Aborting.\n");
2338 }while(ptr < data->payload + data->payload_len);
2342 int dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2344 /* Send as normal trace if possible */
2345 if(header_len+payload_len+sizeof(uint16_t) < DLT_USER_BUF_MAX_SIZE) {
2346 return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload);
2349 /* Allocate Memory */
2350 s_segmented_data *thread_data = malloc(sizeof(s_segmented_data));
2351 if(thread_data == NULL)
2355 thread_data->header = malloc(header_len);
2356 if(thread_data->header == NULL)
2361 thread_data->payload = malloc(payload_len);
2362 if(thread_data->payload == NULL)
2364 free(thread_data->header);
2370 thread_data->handle = handle;
2371 thread_data->nw_trace_type = nw_trace_type;
2372 thread_data->header_len = header_len;
2373 memcpy(thread_data->header, header, header_len);
2374 thread_data->payload_len = payload_len;
2375 memcpy(thread_data->payload, payload, payload_len);
2377 /* Send start message */
2378 DltReturnValue err = dlt_user_trace_network_segmented_start(&(thread_data->id),
2379 thread_data->handle, thread_data->nw_trace_type,
2380 thread_data->header_len, thread_data->header,
2381 thread_data->payload_len);
2382 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2384 dlt_log(LOG_ERR,"NWTSegmented: Could not send start segment. Aborting.\n");
2385 free(thread_data->header);
2386 free(thread_data->payload);
2391 /* Open queue if it is not open */
2392 if(dlt_init_message_queue() < 0)
2394 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2395 free(thread_data->header);
2396 free(thread_data->payload);
2403 if(mq_send(dlt_user.dlt_segmented_queue_write_handle,
2404 (char *)&thread_data, sizeof(s_segmented_data *), 1) < 0)
2408 dlt_log(LOG_ERR, "NWTSegmented: Queue full. Message discarded.\n");
2410 free(thread_data->header);
2411 free(thread_data->payload);
2414 snprintf(str,255,"NWTSegmented: Could not write into queue: %s \n",strerror(errno));
2415 dlt_log(LOG_CRIT, str);
2419 //thread_data will be freed by the receiver function
2420 //coverity[leaked_storage]
2424 int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2426 return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1);
2429 int dlt_user_trace_network_truncated(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload, int allow_truncate)
2433 if (dlt_user_initialised==0)
2441 if (dlt_user_log_init(handle, &log)==-1)
2451 /* Commented out because of DltNetworkTraceType:
2453 if ((nw_trace_type<=0) || (nw_trace_type>0x15))
2460 if (dlt_user.dlt_ll_ts==0)
2465 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2469 log.trace_status = nw_trace_type;
2477 /* If truncation is allowed, check if we must do it */
2478 if(allow_truncate > 0 && (header_len+payload_len+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
2480 /* Identify as truncated */
2481 if(dlt_user_log_write_string(&log, "NWTR") < 0)
2486 /* Write header and its length */
2487 if (dlt_user_log_write_raw(&log, header, header_len) < 0)
2492 /* Write original size of payload */
2493 if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2499 * Calculate maximum avaialble space in sending buffer after headers.
2502 int truncated_payload_len = DLT_USER_BUF_MAX_SIZE -
2503 log.size - sizeof(uint16_t) - sizeof(uint32_t);
2505 /* Write truncated payload */
2506 if (dlt_user_log_write_raw(&log, payload, truncated_payload_len) < 0)
2511 else /* Truncation not allowed or data short enough */
2513 /* Write header and its length */
2514 if (dlt_user_log_write_raw(&log, header, header_len)==-1)
2524 /* Write payload and its length */
2525 if (dlt_user_log_write_raw(&log, payload, payload_len)==-1)
2532 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2538 int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
2542 if (dlt_user.verbose_mode==0)
2547 if ((handle==0) || (text==0))
2552 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2554 if (dlt_user_log_write_string(&log,text)==-1)
2558 if (dlt_user_log_write_finish(&log)==-1)
2567 int dlt_log_string_int(DltContext *handle,DltLogLevelType loglevel, const char *text, int data)
2571 if (dlt_user.verbose_mode==0)
2576 if ((handle==0) || (text==0))
2581 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2583 if (dlt_user_log_write_string(&log,text)==-1)
2587 if (dlt_user_log_write_int(&log,data)==-1)
2591 if (dlt_user_log_write_finish(&log)==-1)
2600 int dlt_log_string_uint(DltContext *handle,DltLogLevelType loglevel, const char *text, unsigned int data)
2604 if (dlt_user.verbose_mode==0)
2609 if ((handle==0) || (text==0))
2614 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2616 if (dlt_user_log_write_string(&log,text)==-1)
2620 if (dlt_user_log_write_uint(&log,data)==-1)
2624 if (dlt_user_log_write_finish(&log)==-1)
2633 int dlt_log_int(DltContext *handle,DltLogLevelType loglevel, int data)
2637 if (dlt_user.verbose_mode==0)
2647 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2649 if (dlt_user_log_write_int(&log,data)==-1)
2653 if (dlt_user_log_write_finish(&log)==-1)
2662 int dlt_log_uint(DltContext *handle,DltLogLevelType loglevel, unsigned int data)
2666 if (dlt_user.verbose_mode==0)
2676 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2678 if (dlt_user_log_write_uint(&log,data)==-1)
2682 if (dlt_user_log_write_finish(&log)==-1)
2691 int dlt_log_raw(DltContext *handle,DltLogLevelType loglevel, void *data,uint16_t length)
2695 if (dlt_user.verbose_mode==0)
2705 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2707 if (dlt_user_log_write_raw(&log,data,length)==-1)
2711 if (dlt_user_log_write_finish(&log)==-1)
2720 int dlt_verbose_mode(void)
2722 if (dlt_user_initialised==0)
2730 /* Switch to verbose mode */
2731 dlt_user.verbose_mode = 1;
2736 int dlt_nonverbose_mode(void)
2738 if (dlt_user_initialised==0)
2746 /* Switch to non-verbose mode */
2747 dlt_user.verbose_mode = 0;
2752 int dlt_enable_local_print(void)
2754 if (dlt_user_initialised==0)
2762 dlt_user.enable_local_print = 1;
2767 int dlt_disable_local_print(void)
2769 if (dlt_user_initialised==0)
2777 dlt_user.enable_local_print = 0;
2782 void dlt_user_receiverthread_function(__attribute__((unused)) void *ptr)
2784 prctl(PR_SET_NAME, "dlt_receiver", 0, 0, 0);
2787 /* Check for new messages from DLT daemon */
2788 if (dlt_user_log_check_user_message()==-1)
2790 /* Critical error */
2791 dlt_log(LOG_CRIT,"Receiver thread encountered error condition\n");
2794 usleep(DLT_USER_RECEIVE_DELAY); /* delay */
2798 /* Private functions of user library */
2800 int dlt_user_log_init(DltContext *handle, DltContextData *log)
2802 if (dlt_user_initialised==0)
2810 log->handle = handle;
2815 int dlt_user_queue_resend(void)
2817 static unsigned char dlt_user_queue_resend_error_counter = 0;
2819 if(dlt_user.dlt_log_handle < 0)
2821 // Fail silenty. FIFO is not open yet
2825 * Ask segmented thread to try emptying the buffer soon.
2826 * This will be freed in dlt_user_trace_network_segmented_thread
2828 s_segmented_data *resend_data = malloc(sizeof(s_segmented_data));
2830 if (NULL == resend_data)
2835 resend_data->payload_len = DLT_DELAYED_RESEND_INDICATOR_PATTERN;
2839 /* Open queue if it is not open */
2840 if(dlt_init_message_queue() < 0)
2842 if(!dlt_user_queue_resend_error_counter)
2844 // log error only when problem occurred first time
2845 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2847 dlt_user_queue_resend_error_counter = 1;
2852 if(mq_send(dlt_user.dlt_segmented_queue_write_handle, (char *)&resend_data, sizeof(s_segmented_data *), 1) < 0)
2854 if(!dlt_user_queue_resend_error_counter)
2856 // log error only when problem occurred first time
2858 snprintf(str,254,"Could not request resending.: %s \n",strerror(errno));
2859 dlt_log(LOG_CRIT, str);
2861 dlt_user_queue_resend_error_counter = 1;
2866 dlt_user_queue_resend_error_counter = 0;
2868 //thread_data will be freed by the receiver function
2869 //coverity[leaked_storage]
2873 DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype)
2876 DltUserHeader userheader;
2879 DltReturnValue ret = DLT_RETURN_OK;
2883 return DLT_RETURN_ERROR;
2888 return DLT_RETURN_ERROR;
2891 if (dlt_user.appID[0]=='\0')
2893 return DLT_RETURN_ERROR;
2896 if (log->handle->contextID[0]=='\0')
2898 return DLT_RETURN_ERROR;
2901 if ((mtype<DLT_TYPE_LOG) || (mtype>DLT_TYPE_CONTROL))
2903 return DLT_RETURN_ERROR;
2906 /* also for Trace messages */
2907 #ifdef DLT_SHM_ENABLE
2908 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_SHM)==-1)
2910 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
2913 return DLT_RETURN_ERROR;
2916 if (dlt_message_init(&msg,0)==-1)
2918 return DLT_RETURN_ERROR;
2921 msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
2923 if (dlt_set_storageheader(msg.storageheader,dlt_user.ecuID)==-1)
2925 return DLT_RETURN_ERROR;
2928 msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
2929 msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_PROTOCOL_VERSION1 ;
2931 if (dlt_user.verbose_mode)
2933 /* In verbose mode, send extended header */
2934 msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2938 /* In non-verbose, send extended header if desired */
2939 #if (DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE==1)
2940 msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2944 #if (BYTE_ORDER==BIG_ENDIAN)
2945 msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
2948 msg.standardheader->mcnt = log->handle->mcnt++;
2950 /* Set header extra parameters */
2951 dlt_set_id(msg.headerextra.ecu,dlt_user.ecuID);
2952 //msg.headerextra.seid = 0;
2953 msg.headerextra.tmsp = dlt_uptime();
2955 if (dlt_message_set_extraparameters(&msg,0)==-1)
2957 return DLT_RETURN_ERROR;
2960 /* Fill out extended header, if extended header should be provided */
2961 if (DLT_IS_HTYP_UEH(msg.standardheader->htyp))
2963 /* with extended header */
2964 msg.extendedheader = (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp) );
2970 msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2973 case DLT_TYPE_NW_TRACE:
2975 msg.extendedheader->msin = (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT) | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2980 /* This case should not occur */
2981 return DLT_RETURN_ERROR;
2986 /* If in verbose mode, set flag in header for verbose mode */
2987 if (dlt_user.verbose_mode)
2989 msg.extendedheader->msin |= DLT_MSIN_VERB;
2992 msg.extendedheader->noar = log->args_num; /* number of arguments */
2993 dlt_set_id(msg.extendedheader->apid,dlt_user.appID); /* application id */
2994 dlt_set_id(msg.extendedheader->ctid,log->handle->contextID); /* context id */
2996 msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
3000 /* without extended header */
3001 msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
3004 len=msg.headersize - sizeof(DltStorageHeader) +log->size;
3007 dlt_log(LOG_CRIT,"Huge message discarded!\n");
3008 return DLT_RETURN_ERROR;
3011 msg.standardheader->len = DLT_HTOBE_16(len);
3013 /* print to std out, if enabled */
3014 if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) &&
3015 (dlt_user.local_print_mode != DLT_PM_AUTOMATIC))
3017 if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
3019 if (dlt_user_print_msg(&msg, log)==-1)
3021 return DLT_RETURN_ERROR;
3026 if (dlt_user.dlt_is_file)
3029 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size);
3034 /* Reattach to daemon if neccesary */
3035 dlt_user_log_reattach_to_daemon();
3037 if (dlt_user.overflow_counter)
3039 if (dlt_user_log_send_overflow()==0)
3041 sprintf(str,"%u messages discarded!\n",dlt_user.overflow_counter);
3042 dlt_log(LOG_ERR, str);
3043 dlt_user.overflow_counter=0;
3047 /* try to resent old data first */
3048 ret = DLT_RETURN_OK;
3049 if(dlt_user.dlt_log_handle!=-1)
3050 ret = dlt_user_log_resend_buffer();
3051 if(ret==DLT_RETURN_OK)
3053 /* resend ok or nothing to resent */
3054 #ifdef DLT_SHM_ENABLE
3055 if(dlt_user.dlt_log_handle!=-1)
3056 dlt_shm_push(&dlt_user.dlt_shm,msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3057 log->buffer, log->size,0,0);
3060 ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
3061 &(userheader), sizeof(DltUserHeader),
3066 #ifdef DLT_TEST_ENABLE
3067 if(dlt_user.corrupt_user_header) {
3068 userheader.pattern[0]=0xff;
3069 userheader.pattern[1]=0xff;
3070 userheader.pattern[2]=0xff;
3071 userheader.pattern[3]=0xff;
3073 if(dlt_user.corrupt_message_size) {
3074 msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
3077 ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
3078 &(userheader), sizeof(DltUserHeader),
3079 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3080 log->buffer, log->size);
3084 /* store message in ringbuffer, if an error has occured */
3085 if (ret!=DLT_RETURN_OK)
3089 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3090 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3091 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3092 log->buffer, log->size)==-1)
3094 if(dlt_user.overflow_counter==0)
3097 dlt_log(LOG_ERR,"Buffer full! Messages will be discarded.\n");
3099 ret = DLT_RETURN_BUFFER_FULL;
3104 // Fail silenty if FIFO is not open
3105 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3107 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_log: Failed to queue resending.\n");
3113 case DLT_RETURN_BUFFER_FULL:
3116 dlt_user.overflow_counter += 1;
3117 return DLT_RETURN_BUFFER_FULL;
3119 case DLT_RETURN_PIPE_FULL:
3121 /* data could not be written */
3122 return DLT_RETURN_PIPE_FULL;
3124 case DLT_RETURN_PIPE_ERROR:
3126 /* handle not open or pipe error */
3127 close(dlt_user.dlt_log_handle);
3128 dlt_user.dlt_log_handle = -1;
3130 #ifdef DLT_SHM_ENABLE
3131 /* free shared memory */
3132 dlt_shm_free_client(&dlt_user.dlt_shm);
3135 if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
3137 dlt_user_print_msg(&msg, log);
3140 return DLT_RETURN_PIPE_ERROR;
3142 case DLT_RETURN_ERROR:
3144 /* other error condition */
3145 return DLT_RETURN_ERROR;
3149 return DLT_RETURN_OK;
3153 /* This case should never occur. */
3154 return DLT_RETURN_ERROR;
3159 return DLT_RETURN_OK;
3162 int dlt_user_log_send_register_application(void)
3164 DltUserHeader userheader;
3165 DltUserControlMsgRegisterApplication usercontext;
3169 if (dlt_user.appID[0]=='\0')
3174 /* set userheader */
3175 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION)==-1)
3180 /* set usercontext */
3181 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3182 usercontext.pid = getpid();
3184 if (dlt_user.application_description!=0)
3186 usercontext.description_length = strlen(dlt_user.application_description);
3190 usercontext.description_length = 0;
3193 if (dlt_user.dlt_is_file)
3199 ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication),dlt_user.application_description,usercontext.description_length);
3201 /* store message in ringbuffer, if an error has occured */
3202 if (ret!=DLT_RETURN_OK)
3206 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3207 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3208 (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterApplication),
3209 (const unsigned char*)dlt_user.application_description, usercontext.description_length)==-1)
3211 dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3218 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3220 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_application: Failed to queue resending.\n");
3227 int dlt_user_log_send_unregister_application(void)
3229 DltUserHeader userheader;
3230 DltUserControlMsgUnregisterApplication usercontext;
3234 if (dlt_user.appID[0]=='\0')
3239 /* set userheader */
3240 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION)==-1)
3245 /* set usercontext */
3246 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3247 usercontext.pid = getpid();
3249 if (dlt_user.dlt_is_file)
3255 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication));
3256 return ((ret==DLT_RETURN_OK)?0:-1);
3259 int dlt_user_log_send_register_context(DltContextData *log)
3261 DltUserHeader userheader;
3262 DltUserControlMsgRegisterContext usercontext;
3275 if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3280 /* set userheader */
3281 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT)==-1)
3286 /* set usercontext */
3287 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3288 dlt_set_id(usercontext.ctid,log->handle->contextID); /* context id */
3289 usercontext.log_level_pos = log->handle->log_level_pos;
3290 usercontext.pid = getpid();
3292 usercontext.log_level = (int8_t)log->log_level;
3293 usercontext.trace_status = (int8_t)log->trace_status;
3295 if (log->context_description!=0)
3297 usercontext.description_length = strlen(log->context_description);
3301 usercontext.description_length = 0;
3304 if (dlt_user.dlt_is_file)
3310 ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext),log->context_description,usercontext.description_length);
3312 /* store message in ringbuffer, if an error has occured */
3313 if (ret!=DLT_RETURN_OK)
3317 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3318 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3319 (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterContext),
3320 (const unsigned char*)log->context_description, usercontext.description_length)==-1)
3322 dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3329 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3331 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_context: Failed to queue resending.\n");
3339 int dlt_user_log_send_unregister_context(DltContextData *log)
3341 DltUserHeader userheader;
3342 DltUserControlMsgUnregisterContext usercontext;
3355 if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3360 /* set userheader */
3361 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT)==-1)
3366 /* set usercontext */
3367 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3368 dlt_set_id(usercontext.ctid,log->handle->contextID); /* context id */
3369 usercontext.pid = getpid();
3371 if (dlt_user.dlt_is_file)
3377 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext));
3378 return ((ret==DLT_RETURN_OK)?0:-1);
3381 int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
3383 DltUserHeader userheader;
3384 DltUserControlMsgAppLogLevelTraceStatus usercontext;
3387 if ((appid==0) || (appid[0]=='\0'))
3392 /* Removed because of DltLogLevelType and DltTraceStatusType
3394 if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
3399 if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
3406 /* set userheader */
3407 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS)==-1)
3412 /* set usercontext */
3413 dlt_set_id(usercontext.apid,appid); /* application id */
3414 usercontext.log_level = loglevel;
3415 usercontext.trace_status = tracestatus;
3417 if (dlt_user.dlt_is_file)
3423 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus));
3424 return ((ret==DLT_RETURN_OK)?0:-1);
3427 int dlt_user_log_send_log_mode(DltUserLogMode mode)
3429 DltUserHeader userheader;
3430 DltUserControlMsgLogMode logmode;
3434 /* set userheader */
3435 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE)==-1)
3441 logmode.log_mode = (unsigned char) mode;
3443 if (dlt_user.dlt_is_file)
3449 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode));
3450 return ((ret==DLT_RETURN_OK)?0:-1);
3453 int dlt_user_print_msg(DltMessage *msg, DltContextData *log)
3455 uint8_t *databuffer_tmp;
3456 int32_t datasize_tmp;
3457 int32_t databuffersize_tmp;
3458 static char text[DLT_USER_TEXT_LENGTH];
3460 if ((msg==0) || (log==0))
3465 /* Save variables before print */
3466 databuffer_tmp = msg->databuffer;
3467 datasize_tmp = msg->datasize;
3468 databuffersize_tmp = msg->databuffersize;
3470 /* Act like a receiver, convert header back to host format */
3471 msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len);
3472 dlt_message_get_extraparameters(msg,0);
3474 msg->databuffer = log->buffer;
3475 msg->datasize = log->size;
3476 msg->databuffersize = log->size;
3478 /* Print message as ASCII */
3479 if (dlt_message_print_ascii(msg,text,DLT_USER_TEXT_LENGTH,0)==-1)
3484 /* Restore variables and set len to BE*/
3485 msg->databuffer = databuffer_tmp;
3486 msg->databuffersize = databuffersize_tmp;
3487 msg->datasize = datasize_tmp;
3489 msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
3494 int dlt_user_log_check_user_message(void)
3501 DltUserHeader *userheader;
3502 DltReceiver *receiver = &(dlt_user.receiver);
3504 DltUserControlMsgLogLevel *usercontextll;
3505 DltUserControlMsgInjection *usercontextinj;
3506 DltUserControlMsgLogState *userlogstate;
3507 unsigned char *userbuffer;
3509 /* For delayed calling of injection callback, to avoid deadlock */
3510 DltUserInjectionCallback delayed_injection_callback;
3511 unsigned char *delayed_inject_buffer = 0;
3512 uint32_t delayed_inject_data_length = 0;
3514 /* Ensure that callback is null before searching for it */
3515 delayed_injection_callback.injection_callback = 0;
3516 delayed_injection_callback.service_id = 0;
3518 if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
3522 if (dlt_receiver_receive_fd(receiver)<=0)
3524 /* No new message available */
3528 /* look through buffer as long as data is in there */
3531 if (receiver->bytesRcvd < (int32_t)sizeof(DltUserHeader))
3536 /* resync if necessary */
3540 userheader = (DltUserHeader*) (receiver->buf+offset);
3542 /* Check for user header pattern */
3543 if (dlt_user_check_userheader(userheader))
3550 while ((int32_t)(sizeof(DltUserHeader)+offset)<=receiver->bytesRcvd);
3552 /* Check for user header pattern */
3553 if (dlt_user_check_userheader(userheader)<0 ||
3554 dlt_user_check_userheader(userheader)==0)
3559 /* Set new start offset */
3562 receiver->buf+=offset;
3563 receiver->bytesRcvd-=offset;
3566 switch (userheader->message)
3568 case DLT_USER_MESSAGE_LOG_LEVEL:
3570 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel)))
3576 usercontextll = (DltUserControlMsgLogLevel*) (receiver->buf+sizeof(DltUserHeader));
3578 /* Update log level and trace status */
3579 if (usercontextll!=0)
3583 if ((usercontextll->log_level_pos >= 0) && (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries))
3585 // printf("Store ll, ts\n");
3586 if (dlt_user.dlt_ll_ts)
3588 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = usercontextll->log_level;
3589 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status = usercontextll->trace_status;
3590 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr)
3591 *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) = usercontextll->log_level;
3592 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr)
3593 *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) = usercontextll->trace_status;
3600 /* keep not read data in buffer */
3601 if (dlt_receiver_remove(receiver,sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel))==-1)
3607 case DLT_USER_MESSAGE_INJECTION:
3609 /* At least, user header, user context, and service id and data_length of injected message is available */
3610 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)))
3616 usercontextinj = (DltUserControlMsgInjection*) (receiver->buf+sizeof(DltUserHeader));
3617 userbuffer = (unsigned char*) (receiver->buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection));
3622 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))
3630 if ((usercontextinj->data_length_inject>0) && (dlt_user.dlt_ll_ts))
3632 /* Check if injection callback is registered for this context */
3633 for (i=0; i<dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks;i++)
3635 if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) &&
3636 (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id == usercontextinj->service_id))
3638 /* Prepare delayed injection callback call */
3639 if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback!=0)
3641 delayed_injection_callback.injection_callback = dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback;
3642 delayed_injection_callback.service_id = usercontextinj->service_id;
3643 delayed_inject_data_length = usercontextinj->data_length_inject;
3644 delayed_inject_buffer = malloc(delayed_inject_data_length);
3645 if(delayed_inject_buffer != 0) {
3646 memcpy(delayed_inject_buffer, userbuffer, delayed_inject_data_length);
3657 /* Delayed injection callback call */
3658 if(delayed_inject_buffer != 0 && delayed_injection_callback.injection_callback != 0) {
3659 delayed_injection_callback.injection_callback(delayed_injection_callback.service_id, delayed_inject_buffer, delayed_inject_data_length);
3660 delayed_injection_callback.injection_callback = 0;
3661 free(delayed_inject_buffer);
3662 delayed_inject_buffer = NULL;
3666 /* keep not read data in buffer */
3667 if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))==-1)
3674 case DLT_USER_MESSAGE_LOG_STATE:
3676 /* At least, user header, user context, and service id and data_length of injected message is available */
3677 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))
3683 userlogstate = (DltUserControlMsgLogState*) (receiver->buf+sizeof(DltUserHeader));
3684 dlt_user.log_state = userlogstate->log_state;
3686 /* keep not read data in buffer */
3687 if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))==-1)
3695 dlt_log(LOG_ERR,"Invalid user message type received!\n");
3697 dlt_receiver_remove(receiver,sizeof(DltUserHeader));
3698 /* In next invocation of while loop, a resync will be triggered if additional data was received */
3711 if (dlt_receiver_move_to_begin(receiver)==-1)
3715 } /* while receive */
3718 return DLT_RETURN_OK;
3721 int dlt_user_log_resend_buffer(void)
3727 /* Send content of ringbuffer */
3729 count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
3732 for (num=0;num<count;num++)
3736 size = dlt_buffer_copy(&(dlt_user.startup_buffer),dlt_user.resend_buffer,sizeof(dlt_user.resend_buffer));
3740 #ifdef DLT_SHM_ENABLE
3741 dlt_shm_push(&dlt_user.dlt_shm,dlt_user.resend_buffer+sizeof(DltUserHeader),size-sizeof(DltUserHeader),0,0,0,0);
3744 ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,sizeof(DltUserHeader),0,0,0,0);
3747 ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,size,0,0,0,0);
3750 /* in case of error, keep message in ringbuffer */
3751 if (ret==DLT_RETURN_OK)
3753 dlt_buffer_remove(&(dlt_user.startup_buffer));
3757 /* keep message in ringbuffer */
3768 void dlt_user_log_reattach_to_daemon(void)
3770 uint32_t num,reregistered=0;
3773 DltContextData log_new;
3775 if (dlt_user.dlt_log_handle<0)
3777 dlt_user.dlt_log_handle=-1;
3779 /* try to open pipe to dlt daemon */
3780 dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK);
3781 if (dlt_user.dlt_log_handle > 0)
3783 if (dlt_user_log_init(&handle,&log_new)==-1)
3788 #ifdef DLT_SHM_ENABLE
3789 /* init shared memory */
3790 if (dlt_shm_init_client(&dlt_user.dlt_shm,DLT_SHM_KEY) < 0)
3792 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
3793 dlt_log(LOG_WARNING, str);
3798 dlt_log(LOG_NOTICE, "Logging re-enabled!\n");
3800 /* Re-register application */
3801 if (dlt_user_log_send_register_application()==-1)
3808 /* Re-register all stored contexts */
3809 for (num=0; num<dlt_user.dlt_ll_ts_num_entries; num++)
3811 /* Re-register stored context */
3812 if ((dlt_user.appID[0]!='\0') && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID[0]!='\0'))
3814 //dlt_set_id(log_new.appID, dlt_user.appID);
3815 dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
3816 handle.log_level_pos = num;
3817 log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
3819 // Release the mutex for sending context registration:
3820 // function dlt_user_log_send_register_context() can take the mutex to write to the DLT buffer. => dead lock
3823 log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
3824 log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
3826 if (dlt_user_log_send_register_context(&log_new)==-1)
3833 // Lock again the mutex
3834 // it is necessary in the for(;;) test, in order to have coherent dlt_user data all over the critical section.
3842 if (reregistered==1)
3844 dlt_user_log_resend_buffer();
3850 int dlt_user_log_send_overflow(void)
3852 DltUserHeader userheader;
3853 DltUserControlMsgBufferOverflow userpayload;
3856 /* set userheader */
3857 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW)==-1)
3862 if (dlt_user.dlt_is_file)
3867 /* set user message parameters */
3868 userpayload.overflow_counter = dlt_user.overflow_counter;
3869 dlt_set_id(userpayload.apid,dlt_user.appID);
3872 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader),
3873 &(userpayload), sizeof(DltUserControlMsgBufferOverflow));
3874 return ((ret==DLT_RETURN_OK)?0:-1);
3877 int dlt_user_check_buffer(int *total_size, int *used_size)
3879 #ifdef DLT_SHM_ENABLE
3880 *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm));
3881 *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm));
3883 *total_size = dlt_buffer_get_total_size(&(dlt_user.startup_buffer));
3884 *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer));
3890 #ifdef DLT_TEST_ENABLE
3891 void dlt_user_test_corrupt_user_header(int enable)
3893 dlt_user.corrupt_user_header = enable;
3895 void dlt_user_test_corrupt_message_size(int enable,int16_t size)
3897 dlt_user.corrupt_message_size = enable;
3898 dlt_user.corrupt_message_size_size = size;