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() */
88 #include "dlt_user_shared.h"
89 #include "dlt_user_shared_cfg.h"
90 #include "dlt_user_cfg.h"
92 static DltUser dlt_user;
93 static int dlt_user_initialised = 0;
95 static char str[DLT_USER_BUFFER_LENGTH];
97 static sem_t dlt_mutex;
98 static pthread_t dlt_receiverthread_handle;
99 static pthread_attr_t dlt_receiverthread_attr;
101 /* Segmented Network Trace */
102 #define DLT_MAX_TRACE_SEGMENT_SIZE 1024
103 #define DLT_MESSAGE_QUEUE_NAME "/dlt_message_queue"
104 #define DLT_DELAYED_RESEND_INDICATOR_PATTERN 0xFFFF
106 /* Mutex to wait on while message queue is not initialized */
107 pthread_mutex_t mq_mutex;
108 pthread_cond_t mq_init_condition;
110 /* Structure to pass data to segmented thread */
114 DltNetworkTraceType nw_trace_type;
117 uint16_t payload_len;
121 /* Function prototypes for internally used functions */
122 static void dlt_user_receiverthread_function(void *ptr);
123 static void dlt_user_atexit_handler(void);
124 static int dlt_user_log_init(DltContext *handle, DltContextData *log);
125 static DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype);
126 static int dlt_user_log_send_register_application(void);
127 static int dlt_user_log_send_unregister_application(void);
128 static int dlt_user_log_send_register_context(DltContextData *log);
129 static int dlt_user_log_send_unregister_context(DltContextData *log);
130 static int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus);
131 static int dlt_user_log_send_log_mode(DltUserLogMode mode);
132 static int dlt_user_print_msg(DltMessage *msg, DltContextData *log);
133 static int dlt_user_log_check_user_message(void);
134 static void dlt_user_log_reattach_to_daemon(void);
135 static int dlt_user_log_send_overflow(void);
136 static void dlt_user_trace_network_segmented_thread(void *unused);
137 static void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data);
138 static int dlt_user_queue_resend(void);
140 int dlt_user_check_library_version(const char *user_major_version,const char *user_minor_version){
143 char lib_major_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
144 char lib_minor_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
146 dlt_get_major_version( lib_major_version);
147 dlt_get_minor_version( lib_minor_version);
149 if( (strcmp(lib_major_version,user_major_version)!=0) || (strcmp(lib_minor_version,user_minor_version)!=0))
151 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);
152 dlt_log(LOG_WARNING, str);
160 char filename[DLT_USER_MAX_FILENAME_LENGTH];
163 dlt_user_initialised = 1;
165 /* Initialize common part of dlt_init()/dlt_init_file() */
166 if (dlt_init_common()==-1)
168 dlt_user_initialised = 0;
172 dlt_user.dlt_is_file = 0;
173 dlt_user.overflow = 0;
174 dlt_user.overflow_counter = 0;
175 #ifdef DLT_SHM_ENABLE
176 memset(&(dlt_user.dlt_shm),0,sizeof(DltShm));
179 /* create and open DLT user FIFO */
180 sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
182 /* Try to delete existing pipe, ignore result of unlink */
185 ret=mkfifo(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH );
188 sprintf(str,"Loging disabled, FIFO user %s cannot be created!\n",filename);
189 dlt_log(LOG_WARNING, str);
190 /* return 0; */ /* removed to prevent error, when FIFO already exists */
193 dlt_user.dlt_user_handle = open(filename, O_RDWR | O_CLOEXEC);
194 if (dlt_user.dlt_user_handle == DLT_FD_INIT)
196 sprintf(str,"Loging disabled, FIFO user %s cannot be opened!\n",filename);
197 dlt_log(LOG_WARNING, str);
202 /* open DLT output FIFO */
203 dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK | O_CLOEXEC );
204 if (dlt_user.dlt_log_handle==-1)
206 sprintf(str,"Loging disabled, FIFO %s cannot be opened with open()!\n",DLT_USER_FIFO);
207 dlt_log(LOG_WARNING, str);
212 #ifdef DLT_SHM_ENABLE
213 /* init shared memory */
214 if (dlt_shm_init_client(&(dlt_user.dlt_shm),DLT_SHM_KEY) < 0)
216 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
217 dlt_log(LOG_WARNING, str);
224 if (dlt_receiver_init(&(dlt_user.receiver),dlt_user.dlt_user_handle, DLT_USER_RCVBUF_MAX_SIZE)==-1)
226 dlt_user_initialised = 0;
230 /* Start receiver thread */
231 if (pthread_create(&(dlt_receiverthread_handle),
233 (void *) &dlt_user_receiverthread_function,
236 if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
238 dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
241 dlt_log(LOG_CRIT, "Can't create receiver thread!\n");
242 dlt_user_initialised = 0;
246 if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
248 dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
251 /* These will be lazy initialized only when needed */
252 dlt_user.dlt_segmented_queue_read_handle = -1;
253 dlt_user.dlt_segmented_queue_write_handle = -1;
255 /* Wait mutext for segmented thread */
256 pthread_mutex_init(&mq_mutex, NULL);
257 pthread_cond_init(&mq_init_condition, NULL);
259 /* Start the segmented thread */
260 if(pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL,
261 (void *)dlt_user_trace_network_segmented_thread, NULL))
263 dlt_log(LOG_CRIT, "Can't start segmented thread!\n");
270 int dlt_init_file(const char *name)
272 dlt_user_initialised = 1;
274 /* Initialize common part of dlt_init()/dlt_init_file() */
275 if (dlt_init_common()==-1)
277 dlt_user_initialised = 0;
281 dlt_user.dlt_is_file = 1;
283 /* open DLT output file */
284 dlt_user.dlt_log_handle = open(name,O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
285 if (dlt_user.dlt_log_handle == -1)
287 sprintf(str,"Log file %s cannot be opened!\n",name);
288 dlt_log(LOG_ERR, str);
295 int dlt_init_message_queue(void)
297 pthread_mutex_lock(&mq_mutex);
298 if(dlt_user.dlt_segmented_queue_read_handle >= 0 &&
299 dlt_user.dlt_segmented_queue_write_handle >= 0)
301 // Already intialized
302 pthread_mutex_unlock(&mq_mutex);
306 /* Generate per process name for queue */
307 char queue_name[NAME_MAX];
308 sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
310 /* Maximum queue size is 10, limit to size of pointers */
311 struct mq_attr mqatr;
313 mqatr.mq_maxmsg = 10;
314 mqatr.mq_msgsize = sizeof(s_segmented_data *);
315 mqatr.mq_curmsgs = 0;
318 * Create the message queue. It must be newly created
319 * if old one was left by a crashing process.
321 dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
322 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
323 if(dlt_user.dlt_segmented_queue_read_handle < 0)
327 dlt_log(LOG_WARNING, "Old message queue exists, trying to delete.\n");
328 if(mq_unlink(queue_name) < 0)
331 snprintf(str,255,"Could not delete existing message queue!: %s \n",strerror(errno));
332 dlt_log(LOG_CRIT, str);
336 dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
337 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
340 if(dlt_user.dlt_segmented_queue_read_handle < 0)
343 snprintf(str,255,"Can't create message queue read handle!: %s \n",strerror(errno));
344 dlt_log(LOG_CRIT, str);
345 pthread_mutex_unlock(&mq_mutex);
350 dlt_user.dlt_segmented_queue_write_handle = mq_open(queue_name, O_WRONLY|O_NONBLOCK);
351 if(dlt_user.dlt_segmented_queue_write_handle < 0)
355 snprintf(str,255,"Can't open message queue write handle!: %s \n",strerror(errno));
356 dlt_log(LOG_CRIT, str);
357 pthread_mutex_unlock(&mq_mutex);
361 pthread_cond_signal(&mq_init_condition);
362 pthread_mutex_unlock(&mq_mutex);
366 int dlt_init_common(void)
368 char *env_local_print;
370 /* Binary semaphore for threads */
371 if (sem_init(&dlt_mutex, 0, 1)==-1)
373 dlt_user_initialised = 0;
377 /* set to unknown state of connected client */
378 dlt_user.log_state = -1;
380 dlt_user.dlt_log_handle=-1;
381 dlt_user.dlt_user_handle=DLT_FD_INIT;
383 dlt_set_id(dlt_user.ecuID,DLT_USER_DEFAULT_ECU_ID);
384 dlt_set_id(dlt_user.appID,"");
386 dlt_user.application_description = 0;
388 /* Verbose mode is enabled by default */
389 dlt_user.verbose_mode = 1;
391 /* Local print is disabled by default */
392 dlt_user.enable_local_print = 0;
394 dlt_user.local_print_mode = DLT_PM_UNSET;
396 env_local_print = getenv(DLT_USER_ENV_LOCAL_PRINT_MODE);
399 if (strcmp(env_local_print,"AUTOMATIC")==0)
401 dlt_user.local_print_mode = DLT_PM_AUTOMATIC;
403 else if (strcmp(env_local_print,"FORCE_ON")==0)
405 dlt_user.local_print_mode = DLT_PM_FORCE_ON;
407 else if (strcmp(env_local_print,"FORCE_OFF")==0)
409 dlt_user.local_print_mode = DLT_PM_FORCE_OFF;
413 /* Initialize LogLevel/TraceStatus field */
415 dlt_user.dlt_ll_ts = 0;
416 dlt_user.dlt_ll_ts_max_num_entries = 0;
417 dlt_user.dlt_ll_ts_num_entries = 0;
419 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)
421 dlt_user_initialised = 0;
427 signal(SIGPIPE,SIG_IGN); /* ignore pipe signals */
429 atexit(dlt_user_atexit_handler);
431 #ifdef DLT_TEST_ENABLE
432 dlt_user.corrupt_user_header = 0;
433 dlt_user.corrupt_message_size = 0;
434 dlt_user.corrupt_message_size_size = 0;
440 void dlt_user_atexit_handler(void)
442 if (dlt_user_initialised==0)
447 /* Try to resend potential log messages in the user buffer */
448 int count = dlt_user_atexit_blow_out_user_buffer();
452 sprintf(tmp,"Lost log messages in user buffer when exiting: %i\n",count);
453 dlt_log(LOG_ERR, tmp);
456 /* Unregister app (this also unregisters all contexts in daemon) */
457 /* Ignore return value */
458 dlt_unregister_app();
461 /* Ignore return value */
465 int dlt_user_atexit_blow_out_user_buffer(void){
469 uint32_t exitTime = dlt_uptime() + DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT;
471 while(dlt_uptime() < exitTime ){
473 ret = dlt_user_log_resend_buffer();
480 usleep(DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP);
484 count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
493 char filename[DLT_USER_MAX_FILENAME_LENGTH];
495 if (dlt_user_initialised==0)
500 if (dlt_receiverthread_handle)
502 /* Ignore return value */
503 pthread_cancel(dlt_receiverthread_handle);
506 if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
508 sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
510 close(dlt_user.dlt_user_handle);
511 dlt_user.dlt_user_handle=DLT_FD_INIT;
516 #ifdef DLT_SHM_ENABLE
517 /* free shared memory */
518 dlt_shm_free_client(&dlt_user.dlt_shm);
521 if (dlt_user.dlt_log_handle!=-1)
523 /* close log file/output fifo to daemon */
524 close(dlt_user.dlt_log_handle);
525 dlt_user.dlt_log_handle = -1;
528 /* Ignore return value */
529 dlt_receiver_free(&(dlt_user.receiver));
531 /* Ignore return value */
532 dlt_buffer_free_dynamic(&(dlt_user.startup_buffer));
535 if (dlt_user.dlt_ll_ts)
537 for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
539 if (dlt_user.dlt_ll_ts[i].injection_table!=0)
541 free(dlt_user.dlt_ll_ts[i].injection_table);
542 dlt_user.dlt_ll_ts[i].injection_table = 0;
544 dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
547 free(dlt_user.dlt_ll_ts);
548 dlt_user.dlt_ll_ts = 0;
549 dlt_user.dlt_ll_ts_max_num_entries = 0;
550 dlt_user.dlt_ll_ts_num_entries = 0;
554 if (dlt_user.dlt_segmented_nwt_handle)
556 pthread_cancel(dlt_user.dlt_segmented_nwt_handle);
559 char queue_name[NAME_MAX];
560 sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
563 * Ignore errors from these, to not to spam user if dlt_free
564 * is accidentally called multiple times.
566 mq_close(dlt_user.dlt_segmented_queue_write_handle);
567 mq_close(dlt_user.dlt_segmented_queue_read_handle);
568 mq_unlink(queue_name);
570 dlt_user_initialised = 0;
575 int dlt_check_library_version(const char * user_major_version,const char * user_minor_version)
577 return dlt_user_check_library_version(user_major_version, user_minor_version);
580 int dlt_register_app(const char *appid, const char * description)
584 if (dlt_user_initialised==0)
592 if ((appid==0) || (appid[0]=='\0'))
597 /* check if application already registered */
598 /* if yes do not register again */
601 if(appid[0]==dlt_user.appID[0])
606 if(appid[0]==dlt_user.appID[0] &&
607 appid[1]==dlt_user.appID[1])
612 if(appid[0]==dlt_user.appID[0] &&
613 appid[1]==dlt_user.appID[1] &&
614 appid[2]==dlt_user.appID[2])
619 if(appid[0]==dlt_user.appID[0] &&
620 appid[1]==dlt_user.appID[1] &&
621 appid[2]==dlt_user.appID[2] &&
622 appid[3]==dlt_user.appID[3])
628 /* Store locally application id and application description */
629 dlt_set_id(dlt_user.appID, appid);
631 if (dlt_user.application_description!=0)
633 free(dlt_user.application_description);
636 dlt_user.application_description = 0;
640 size_t desc_len = strlen(description);
641 dlt_user.application_description= malloc(desc_len+1);
642 if (dlt_user.application_description){
643 strncpy(dlt_user.application_description, description, desc_len);
645 /* Terminate transmitted string with 0 */
646 dlt_user.application_description[desc_len]='\0';
657 ret = dlt_user_log_send_register_application();
661 int dlt_register_context(DltContext *handle, const char *contextid, const char * description)
663 if (dlt_user_initialised==0)
673 if (dlt_user.appID[0]=='\0')
675 dlt_log(LOG_ERR, "no application registered!\n");
681 if ((contextid==0) || (contextid[0]=='\0'))
689 return dlt_register_context_ll_ts(handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET);
692 int dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const char * description, int loglevel, int tracestatus)
697 char ctid[DLT_ID_SIZE+1];
699 if (dlt_user_initialised==0)
709 if (dlt_user.appID[0]=='\0')
711 dlt_log(LOG_ERR, "no application registered!\n");
719 if ((contextid==0) || (contextid[0]=='\0'))
724 if ((loglevel<DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel>DLT_LOG_VERBOSE) || (loglevel==DLT_LOG_DEFAULT))
729 if ((tracestatus<DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus>DLT_TRACE_STATUS_ON) || (tracestatus==DLT_TRACE_STATUS_DEFAULT))
734 if (dlt_user_log_init(handle, &log)==-1)
739 /* Reset message counter */
742 /* Store context id in log level/trace status field */
744 /* Check if already registered, else register context */
748 for (i=0;i<dlt_user.dlt_ll_ts_num_entries;i++)
750 if (dlt_user.dlt_ll_ts)
752 if (memcmp(dlt_user.dlt_ll_ts[i].contextID, contextid,DLT_ID_SIZE)==0)
756 memset(ctid,0,(DLT_ID_SIZE+1));
757 dlt_print_id(ctid, contextid);
759 sprintf(str,"context '%s' already registered!\n",ctid);
760 dlt_log(LOG_WARNING, str);
769 /* Allocate or expand context array */
770 if (dlt_user.dlt_ll_ts == 0)
772 dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*DLT_USER_CONTEXT_ALLOC_SIZE);
773 if (dlt_user.dlt_ll_ts==0)
779 dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE;
781 /* Initialize new entries */
782 for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
784 dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
786 /* At startup, logging and tracing is locally enabled */
787 /* the correct log level/status is set after received from daemon */
788 dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
789 dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
791 dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
792 dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
794 dlt_user.dlt_ll_ts[i].context_description = 0;
796 dlt_user.dlt_ll_ts[i].injection_table = 0;
797 dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
802 if ((dlt_user.dlt_ll_ts_num_entries%DLT_USER_CONTEXT_ALLOC_SIZE)==0)
804 /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
805 dlt_ll_ts_type *old_ll_ts;
806 uint32_t old_max_entries;
808 old_ll_ts = dlt_user.dlt_ll_ts;
809 old_max_entries = dlt_user.dlt_ll_ts_max_num_entries;
811 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;
812 dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*
813 dlt_user.dlt_ll_ts_max_num_entries);
814 if (dlt_user.dlt_ll_ts==0)
816 dlt_user.dlt_ll_ts = old_ll_ts;
817 dlt_user.dlt_ll_ts_max_num_entries = old_max_entries;
822 memcpy(dlt_user.dlt_ll_ts,old_ll_ts,sizeof(dlt_ll_ts_type)*dlt_user.dlt_ll_ts_num_entries);
825 /* Initialize new entries */
826 for (i=dlt_user.dlt_ll_ts_num_entries;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
828 dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
830 /* At startup, logging and tracing is locally enabled */
831 /* the correct log level/status is set after received from daemon */
832 dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
833 dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
835 dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
836 dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
838 dlt_user.dlt_ll_ts[i].context_description = 0;
840 dlt_user.dlt_ll_ts[i].injection_table = 0;
841 dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
846 /* Store locally context id and context description */
847 dlt_set_id(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].contextID, contextid);
849 if (dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description!=0)
851 free(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description);
854 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = 0;
858 size_t desc_len = strlen(description);
859 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = malloc(desc_len+1);
860 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description == 0)
866 strncpy(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description, description, desc_len);
868 /* Terminate transmitted string with 0 */
869 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description[desc_len]='\0';
872 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
874 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr = malloc(sizeof(int8_t));
875 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
881 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
883 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr = malloc(sizeof(int8_t));
884 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
891 if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
893 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = loglevel;
896 if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
898 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
901 /* Prepare transfer struct */
902 //dlt_set_id(log->appID, dlt_user.appID);
903 dlt_set_id(handle->contextID, contextid);
904 handle->log_level_pos = dlt_user.dlt_ll_ts_num_entries;
906 handle->log_level_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr;
907 handle->trace_status_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr;
909 log.context_description = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description;
911 *(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;
912 *(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;
914 if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
916 log.log_level = loglevel;
920 log.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
923 if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
925 log.trace_status = tracestatus;
929 log.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
932 dlt_user.dlt_ll_ts_num_entries++;
936 ret=dlt_user_log_send_register_context(&log);
948 int dlt_unregister_app(void)
952 if (dlt_user_initialised==0)
957 /* Inform daemon to unregister application and all of its contexts */
958 ret = dlt_user_log_send_unregister_application();
962 /* Clear and free local stored application information */
963 dlt_set_id(dlt_user.appID, "");
965 if (dlt_user.application_description!=0)
967 free(dlt_user.application_description);
970 dlt_user.application_description = 0;
977 int dlt_unregister_context(DltContext *handle)
982 if (dlt_user_initialised==0)
987 if (dlt_user_log_init(handle, &log) == -1)
994 handle->log_level_ptr = 0;
995 handle->trace_status_ptr = 0;
997 if (dlt_user.dlt_ll_ts)
999 /* Clear and free local stored context information */
1000 dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, "");
1002 dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
1003 dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
1005 if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description!=0)
1007 free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
1010 if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr!=0)
1012 free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr);
1013 dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = 0;
1016 if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr!=0)
1018 free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr);
1019 dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = 0;
1022 dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = 0;
1024 if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table)
1026 free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
1027 dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = 0;
1030 dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks = 0;
1035 /* Inform daemon to unregister context */
1036 ret = dlt_user_log_send_unregister_context(&log);
1041 int dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus)
1046 if (dlt_user_initialised==0)
1054 /* Removed because of DltLogLevelType and DltTraceStatusType
1056 if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
1061 if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
1066 if (dlt_user.dlt_ll_ts==0)
1075 /* Update local structures */
1076 for (i=0; i<dlt_user.dlt_ll_ts_num_entries;i++)
1078 dlt_user.dlt_ll_ts[i].log_level = loglevel;
1079 dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
1080 if(dlt_user.dlt_ll_ts[i].log_level_ptr)
1081 *(dlt_user.dlt_ll_ts[i].log_level_ptr) = loglevel;
1082 if(dlt_user.dlt_ll_ts[i].trace_status_ptr)
1083 *(dlt_user.dlt_ll_ts[i].trace_status_ptr) = tracestatus;
1088 /* Inform DLT server about update */
1089 ret = dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus);
1094 int dlt_get_log_state()
1096 return dlt_user.log_state;
1099 int dlt_set_log_mode(DltUserLogMode mode)
1101 if (dlt_user_initialised==0)
1109 return dlt_user_log_send_log_mode(mode);
1112 int dlt_forward_msg(void *msgdata,size_t size)
1114 DltUserHeader userheader;
1117 if ((msgdata==0) || (size==0))
1122 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
1124 /* Type of internal user message; same value for Trace messages */
1128 if (dlt_user.dlt_is_file)
1131 ret = dlt_user_log_out2(dlt_user.dlt_log_handle, msgdata, size, 0, 0);
1132 return ((ret==DLT_RETURN_OK)?0:-1);
1136 /* Reattach to daemon if neccesary */
1137 dlt_user_log_reattach_to_daemon();
1139 if (dlt_user.overflow_counter)
1141 if (dlt_user_log_send_overflow()==0)
1143 sprintf(str,"Buffer full! %u messages discarded!\n",dlt_user.overflow_counter);
1144 dlt_log(LOG_ERR, str);
1145 dlt_user.overflow_counter=0; }
1149 ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
1150 &(userheader), sizeof(DltUserHeader),
1151 msgdata, size, 0, 0);
1153 /* store message in ringbuffer, if an error has occured */
1154 if (ret!=DLT_RETURN_OK)
1158 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
1159 (unsigned char *)&(userheader), sizeof(DltUserHeader),
1160 msgdata, size, 0, 0)==-1)
1162 if(dlt_user.overflow_counter==0)
1164 dlt_log(LOG_ERR,"Buffer full! First message discarded!\n");
1166 ret = DLT_RETURN_BUFFER_FULL;
1171 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
1173 ;//dlt_log(LOG_WARNING, "dlt_forward_msg: Failed to queue resending.\n");
1179 case DLT_RETURN_BUFFER_FULL:
1182 dlt_user.overflow_counter += 1;
1185 case DLT_RETURN_PIPE_FULL:
1187 /* data could not be written */
1190 case DLT_RETURN_PIPE_ERROR:
1192 /* handle not open or pipe error */
1193 close(dlt_user.dlt_log_handle);
1194 dlt_user.dlt_log_handle = -1;
1198 case DLT_RETURN_ERROR:
1200 /* other error condition */
1209 /* This case should not occur */
1218 /* ********************************************************************************************* */
1220 inline int dlt_user_log_write_start(DltContext *handle, DltContextData *log,DltLogLevelType loglevel)
1222 return dlt_user_log_write_start_id(handle,log,loglevel,DLT_USER_DEFAULT_MSGID);
1225 int dlt_user_log_write_start_id(DltContext *handle, DltContextData *log,DltLogLevelType loglevel, uint32_t messageid)
1227 if(dlt_user_initialised==0)
1239 if (dlt_user_log_init(handle, log)==-1)
1244 if (dlt_user.dlt_ll_ts==0)
1249 if (handle->log_level_ptr && (loglevel<=(int)*(handle->log_level_ptr) ) && (loglevel!=0))
1252 log->log_level = loglevel;
1254 /* In non-verbose mode, insert message id */
1255 if (dlt_user.verbose_mode==0)
1257 if ((sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1261 /* Write message id */
1262 memcpy(log->buffer,&(messageid),sizeof(uint32_t));
1263 log->size = sizeof(uint32_t);
1265 /* as the message id is part of each message in non-verbose mode,
1266 it doesn't increment the argument counter in extended header (if used) */
1275 int dlt_user_log_write_finish(DltContextData *log)
1282 return dlt_user_log_send_log(log, DLT_TYPE_LOG) < 0 ? -1 : 0;
1285 int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length)
1295 if ((log->size+length+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1300 if (dlt_user.verbose_mode)
1302 if ((log->size+length+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1307 /* Transmit type information */
1308 type_info = DLT_TYPE_INFO_RAWD;
1310 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1311 log->size += sizeof(uint32_t);
1315 /* First transmit length of raw data, then the raw data itself */
1316 arg_size = (uint16_t)length;
1318 memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1319 log->size += sizeof(uint16_t);
1321 memcpy((log->buffer)+log->size,data,arg_size);
1322 log->size += arg_size;
1329 int dlt_user_log_write_float32(DltContextData *log, float32_t data)
1338 if (sizeof(float32_t)!=4)
1343 if ((log->size+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1348 if (dlt_user.verbose_mode)
1350 if ((log->size+sizeof(uint32_t)+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1355 type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
1357 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1358 log->size += sizeof(uint32_t);
1361 memcpy((log->buffer)+log->size,&data, sizeof(float32_t));
1362 log->size += sizeof(float32_t);
1369 int dlt_user_log_write_float64(DltContextData *log, float64_t data)
1378 if (sizeof(float64_t)!=8)
1383 if ((log->size+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1388 if (dlt_user.verbose_mode)
1390 if ((log->size+sizeof(uint32_t)+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1395 type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
1397 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1398 log->size += sizeof(uint32_t);
1401 memcpy((log->buffer)+log->size,&data, sizeof(float64_t));
1402 log->size += sizeof(float64_t);
1409 int dlt_user_log_write_uint( DltContextData *log, unsigned int data)
1416 switch (sizeof(unsigned int))
1420 return dlt_user_log_write_uint8(log, (uint8_t)data);
1425 return dlt_user_log_write_uint16(log, (uint16_t)data);
1430 return dlt_user_log_write_uint32(log, (uint32_t)data);
1435 return dlt_user_log_write_uint64(log, (uint64_t)data);
1448 int dlt_user_log_write_uint8(DltContextData *log, uint8_t data)
1457 if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1462 if (dlt_user.verbose_mode)
1464 if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1469 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
1471 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1472 log->size += sizeof(uint32_t);
1475 memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1476 log->size += sizeof(uint8_t);
1483 int dlt_user_log_write_uint16(DltContextData *log, uint16_t data)
1492 if ((log->size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1497 if (dlt_user.verbose_mode)
1499 if ((log->size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1504 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
1506 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1507 log->size += sizeof(uint32_t);
1510 memcpy((log->buffer)+log->size,&data,sizeof(uint16_t));
1511 log->size += sizeof(uint16_t);
1518 int dlt_user_log_write_uint32(DltContextData *log, uint32_t data)
1527 if ((log->size+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1532 if (dlt_user.verbose_mode)
1534 if ((log->size+sizeof(uint32_t)+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1539 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
1541 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1542 log->size += sizeof(uint32_t);
1545 memcpy((log->buffer)+log->size,&data, sizeof(uint32_t));
1546 log->size += sizeof(uint32_t);
1553 int dlt_user_log_write_uint64(DltContextData *log, uint64_t data)
1562 if ((log->size+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1567 if (dlt_user.verbose_mode)
1569 if ((log->size+sizeof(uint32_t)+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1574 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
1576 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1577 log->size +=sizeof(uint32_t);
1580 memcpy((log->buffer)+log->size,&data,sizeof(uint64_t));
1581 log->size += sizeof(uint64_t);
1588 int dlt_user_log_write_int(DltContextData *log, int data)
1595 switch (sizeof(int))
1599 return dlt_user_log_write_int8(log, (int8_t)data);
1604 return dlt_user_log_write_int16(log, (int16_t)data);
1609 return dlt_user_log_write_int32(log, (int32_t)data);
1614 return dlt_user_log_write_int64(log, (int64_t)data);
1627 int dlt_user_log_write_int8(DltContextData *log, int8_t data)
1636 if ((log->size+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1641 if (dlt_user.verbose_mode)
1643 if ((log->size+sizeof(uint32_t)+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1648 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
1650 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1651 log->size += sizeof(uint32_t);
1654 memcpy((log->buffer)+log->size,&data,sizeof(int8_t));
1655 log->size += sizeof(int8_t);
1662 int dlt_user_log_write_int16(DltContextData *log, int16_t data)
1671 if ((log->size+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1676 if (dlt_user.verbose_mode)
1678 if ((log->size+sizeof(uint32_t)+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1683 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
1685 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1686 log->size += sizeof(uint32_t);
1689 memcpy((log->buffer)+log->size,&data,sizeof(int16_t));
1690 log->size += sizeof(int16_t);
1697 int dlt_user_log_write_int32(DltContextData *log, int32_t data)
1706 if ((log->size+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1711 if (dlt_user.verbose_mode)
1713 if ((log->size+sizeof(uint32_t)+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1718 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
1720 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1721 log->size += sizeof(uint32_t);
1724 memcpy((log->buffer)+log->size,&data, sizeof(int32_t));
1725 log->size += sizeof(int32_t);
1732 int dlt_user_log_write_int64(DltContextData *log, int64_t data)
1741 if ((log->size+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1746 if (dlt_user.verbose_mode)
1748 if ((log->size+sizeof(uint32_t)+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1753 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
1755 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1756 log->size += sizeof(uint32_t);
1759 memcpy((log->buffer)+log->size,&data,sizeof(int64_t));
1760 log->size += sizeof(int64_t);
1767 int dlt_user_log_write_bool(DltContextData *log, uint8_t data)
1776 if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1781 if (dlt_user.verbose_mode)
1783 if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1788 type_info = DLT_TYPE_INFO_BOOL;
1790 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1791 log->size += sizeof(uint32_t);
1794 memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1795 log->size += sizeof(uint8_t);
1802 int dlt_user_log_write_string(DltContextData *log, const char *text)
1807 if ((log==0) || (text==0))
1812 if ((log->size+(strlen(text)+1)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1817 if (dlt_user.verbose_mode)
1819 if ((log->size+(strlen(text)+1)+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1824 type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII;
1826 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1827 log->size += sizeof(uint32_t);
1830 arg_size = strlen(text) + 1;
1832 memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1833 log->size += sizeof(uint16_t);
1835 memcpy((log->buffer)+log->size,text,arg_size);
1836 log->size += arg_size;
1843 int dlt_user_log_write_utf8_string(DltContextData *log, const char *text)
1848 if ((log==0) || (text==0))
1853 arg_size = strlen(text)+1;
1855 if ((log->size+arg_size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1860 if (dlt_user.verbose_mode)
1862 if ((log->size+arg_size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1867 type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8;
1869 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1870 log->size += sizeof(uint32_t);
1873 arg_size = strlen(text) + 1;
1875 memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1876 log->size += sizeof(uint16_t);
1878 memcpy((log->buffer)+log->size,text,arg_size);
1879 log->size += arg_size;
1886 int dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
1887 int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length))
1893 DltUserInjectionCallback *old;
1900 if (dlt_user_log_init(handle, &log)==-1)
1905 if (service_id<DLT_USER_INJECTION_MIN)
1909 /* This function doesn't make sense storing to local file is choosen;
1910 so terminate this function */
1911 if (dlt_user.dlt_is_file)
1918 if (dlt_user.dlt_ll_ts==0)
1924 /* Insert callback in corresponding table */
1925 i=handle->log_level_pos;
1927 /* Insert each service_id only once */
1928 for (k=0;k<dlt_user.dlt_ll_ts[i].nrcallbacks;k++)
1930 if ((dlt_user.dlt_ll_ts[i].injection_table) &&
1931 (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id))
1944 j=dlt_user.dlt_ll_ts[i].nrcallbacks;
1946 /* Allocate or expand injection table */
1947 if (dlt_user.dlt_ll_ts[i].injection_table == 0)
1949 dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback));
1950 if(dlt_user.dlt_ll_ts[i].injection_table == 0)
1958 old = dlt_user.dlt_ll_ts[i].injection_table;
1959 dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback)*(j+1));
1960 if(dlt_user.dlt_ll_ts[i].injection_table == 0)
1962 dlt_user.dlt_ll_ts[i].injection_table = old;
1966 memcpy(dlt_user.dlt_ll_ts[i].injection_table,old,sizeof(DltUserInjectionCallback)*j);
1970 dlt_user.dlt_ll_ts[i].nrcallbacks++;
1973 /* Store service_id and corresponding function pointer for callback function */
1974 dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id;
1975 dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = dlt_injection_callback;
1988 int total_size, used_size;
1989 dlt_user_check_buffer(&total_size, &used_size);
1991 if((total_size - used_size) < (total_size/2))
1999 * Send the start of a segment chain.
2000 * Returns -1 on failure
2002 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)
2013 if (dlt_user_log_init(handle, &log)==-1)
2019 if (dlt_user.dlt_ll_ts==0)
2024 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2028 log.trace_status = nw_trace_type;
2031 gettimeofday(&tv, NULL);
2034 /* Write identifier */
2035 if(dlt_user_log_write_string(&log, "NWST") < 0)
2040 /* Write stream handle */
2041 if(dlt_user_log_write_uint16(&log, *id) < 0)
2047 if(dlt_user_log_write_raw(&log, header, header_len) < 0)
2052 /* Write size of payload */
2053 if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2058 /* Write expected segment count */
2059 uint16_t segment_count = payload_len/DLT_MAX_TRACE_SEGMENT_SIZE+1;
2061 /* If segments align perfectly with segment size, avoid sending empty segment */
2062 if((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0)
2067 if(dlt_user_log_write_uint16(&log, segment_count) < 0)
2072 /* Write length of one segment */
2073 if(dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0)
2079 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2084 int dlt_user_trace_network_segmented_segment(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
2086 while(check_buffer() < 0)
2088 usleep(1000*50); // Wait 50ms
2089 dlt_user_log_resend_buffer();
2099 if (dlt_user_log_init(handle, &log)==-1)
2104 if (dlt_user.dlt_ll_ts==0)
2109 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2113 log.trace_status = nw_trace_type;
2116 /* Write identifier */
2117 if(dlt_user_log_write_string(&log, "NWCH") < 0)
2122 /* Write stream handle */
2123 if(dlt_user_log_write_uint16(&log, id) < 0)
2128 /* Write segment sequence number */
2129 if(dlt_user_log_write_uint16(&log, sequence) < 0)
2135 if(dlt_user_log_write_raw(&log, payload, payload_len) < 0)
2141 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2144 /* Allow other threads to log between chunks */
2149 int dlt_user_trace_network_segmented_end(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type)
2158 if (dlt_user_log_init(handle, &log)==-1)
2165 if (dlt_user.dlt_ll_ts==0)
2170 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2174 log.trace_status = nw_trace_type;
2177 /* Write identifier */
2178 if(dlt_user_log_write_string(&log, "NWEN") < 0)
2183 /* Write stream handle */
2184 if(dlt_user_log_write_uint(&log, id) < 0)
2190 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2196 void dlt_user_trace_network_segmented_thread(void *unused)
2198 /* Unused on purpose. */
2201 s_segmented_data *data;
2205 // Wait until message queue is initialized
2206 pthread_mutex_lock(&mq_mutex);
2207 if(dlt_user.dlt_segmented_queue_read_handle < 0)
2209 pthread_cond_wait(&mq_init_condition, &mq_mutex);
2211 pthread_mutex_unlock(&mq_mutex);
2213 ssize_t read = mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char *)&data,
2214 sizeof(s_segmented_data * ), NULL);
2216 if(read != sizeof(s_segmented_data *))
2220 snprintf(str,254,"NWTSegmented: Error while reading queue: %s \n",strerror(errno));
2221 dlt_log(LOG_CRIT, str);
2225 /* Indicator just to try to flush the buffer */
2226 if(data->payload_len == DLT_DELAYED_RESEND_INDICATOR_PATTERN)
2228 // Sleep 100ms, to allow other process to read FIFO
2230 if(dlt_user_log_resend_buffer() < 0)
2232 // Requeue if still not empty
2233 if ( dlt_user_queue_resend() < 0 )
2235 //dlt_log(LOG_WARNING, "Failed to queue resending in dlt_user_trace_network_segmented_thread.\n");
2242 dlt_user_trace_network_segmented_thread_segmenter(data);
2244 /* Send the end message */
2245 DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type);
2246 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2248 dlt_log(LOG_ERR,"NWTSegmented: Could not send end segment.\n");
2251 /* Free resources */
2253 free(data->payload);
2258 void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data)
2260 /* Segment the data and send the chunks */
2262 uint16_t offset = 0;
2263 uint16_t sequence = 0;
2267 if(offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len)
2269 len = data->payload_len - offset;
2273 len = DLT_MAX_TRACE_SEGMENT_SIZE;
2275 /* If payload size aligns perfectly with segment size, avoid sending empty segment */
2281 ptr = data->payload + offset;
2282 DltReturnValue err = dlt_user_trace_network_segmented_segment(data->id, data->handle, data->nw_trace_type, sequence++, len, ptr);
2283 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2285 dlt_log(LOG_ERR,"NWTSegmented: Could not send segment. Aborting.\n");
2289 }while(ptr < data->payload + data->payload_len);
2293 int dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2295 /* Send as normal trace if possible */
2296 if(header_len+payload_len+sizeof(uint16_t) < DLT_USER_BUF_MAX_SIZE) {
2297 return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload);
2300 /* Allocate Memory */
2301 s_segmented_data *thread_data = malloc(sizeof(s_segmented_data));
2302 if(thread_data == NULL)
2306 thread_data->header = malloc(header_len);
2307 if(thread_data->header == NULL)
2312 thread_data->payload = malloc(payload_len);
2313 if(thread_data->payload == NULL)
2315 free(thread_data->header);
2321 thread_data->handle = handle;
2322 thread_data->nw_trace_type = nw_trace_type;
2323 thread_data->header_len = header_len;
2324 memcpy(thread_data->header, header, header_len);
2325 thread_data->payload_len = payload_len;
2326 memcpy(thread_data->payload, payload, payload_len);
2328 /* Send start message */
2329 DltReturnValue err = dlt_user_trace_network_segmented_start(&(thread_data->id),
2330 thread_data->handle, thread_data->nw_trace_type,
2331 thread_data->header_len, thread_data->header,
2332 thread_data->payload_len);
2333 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2335 dlt_log(LOG_ERR,"NWTSegmented: Could not send start segment. Aborting.\n");
2336 free(thread_data->header);
2337 free(thread_data->payload);
2342 /* Open queue if it is not open */
2343 if(dlt_init_message_queue() < 0)
2345 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2346 free(thread_data->header);
2347 free(thread_data->payload);
2354 if(mq_send(dlt_user.dlt_segmented_queue_write_handle,
2355 (char *)&thread_data, sizeof(s_segmented_data *), 1) < 0)
2359 dlt_log(LOG_ERR, "NWTSegmented: Queue full. Message discarded.\n");
2361 free(thread_data->header);
2362 free(thread_data->payload);
2365 snprintf(str,255,"NWTSegmented: Could not write into queue: %s \n",strerror(errno));
2366 dlt_log(LOG_CRIT, str);
2370 //thread_data will be freed by the receiver function
2371 //coverity[leaked_storage]
2375 int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2377 return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1);
2380 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)
2384 if (dlt_user_initialised==0)
2392 if (dlt_user_log_init(handle, &log)==-1)
2402 /* Commented out because of DltNetworkTraceType:
2404 if ((nw_trace_type<=0) || (nw_trace_type>0x15))
2411 if (dlt_user.dlt_ll_ts==0)
2416 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2420 log.trace_status = nw_trace_type;
2428 /* If truncation is allowed, check if we must do it */
2429 if(allow_truncate > 0 && (header_len+payload_len+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
2431 /* Identify as truncated */
2432 if(dlt_user_log_write_string(&log, "NWTR") < 0)
2437 /* Write header and its length */
2438 if (dlt_user_log_write_raw(&log, header, header_len) < 0)
2443 /* Write original size of payload */
2444 if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2450 * Calculate maximum avaialble space in sending buffer after headers.
2453 int truncated_payload_len = DLT_USER_BUF_MAX_SIZE -
2454 log.size - sizeof(uint16_t) - sizeof(uint32_t);
2456 /* Write truncated payload */
2457 if (dlt_user_log_write_raw(&log, payload, truncated_payload_len) < 0)
2462 else /* Truncation not allowed or data short enough */
2464 /* Write header and its length */
2465 if (dlt_user_log_write_raw(&log, header, header_len)==-1)
2475 /* Write payload and its length */
2476 if (dlt_user_log_write_raw(&log, payload, payload_len)==-1)
2483 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2489 int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
2493 if (dlt_user.verbose_mode==0)
2498 if ((handle==0) || (text==0))
2503 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2505 if (dlt_user_log_write_string(&log,text)==-1)
2509 if (dlt_user_log_write_finish(&log)==-1)
2518 int dlt_log_string_int(DltContext *handle,DltLogLevelType loglevel, const char *text, int data)
2522 if (dlt_user.verbose_mode==0)
2527 if ((handle==0) || (text==0))
2532 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2534 if (dlt_user_log_write_string(&log,text)==-1)
2538 if (dlt_user_log_write_int(&log,data)==-1)
2542 if (dlt_user_log_write_finish(&log)==-1)
2551 int dlt_log_string_uint(DltContext *handle,DltLogLevelType loglevel, const char *text, unsigned int data)
2555 if (dlt_user.verbose_mode==0)
2560 if ((handle==0) || (text==0))
2565 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2567 if (dlt_user_log_write_string(&log,text)==-1)
2571 if (dlt_user_log_write_uint(&log,data)==-1)
2575 if (dlt_user_log_write_finish(&log)==-1)
2584 int dlt_log_int(DltContext *handle,DltLogLevelType loglevel, int data)
2588 if (dlt_user.verbose_mode==0)
2598 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2600 if (dlt_user_log_write_int(&log,data)==-1)
2604 if (dlt_user_log_write_finish(&log)==-1)
2613 int dlt_log_uint(DltContext *handle,DltLogLevelType loglevel, unsigned int data)
2617 if (dlt_user.verbose_mode==0)
2627 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2629 if (dlt_user_log_write_uint(&log,data)==-1)
2633 if (dlt_user_log_write_finish(&log)==-1)
2642 int dlt_log_raw(DltContext *handle,DltLogLevelType loglevel, void *data,uint16_t length)
2646 if (dlt_user.verbose_mode==0)
2656 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2658 if (dlt_user_log_write_raw(&log,data,length)==-1)
2662 if (dlt_user_log_write_finish(&log)==-1)
2671 int dlt_verbose_mode(void)
2673 if (dlt_user_initialised==0)
2681 /* Switch to verbose mode */
2682 dlt_user.verbose_mode = 1;
2687 int dlt_nonverbose_mode(void)
2689 if (dlt_user_initialised==0)
2697 /* Switch to non-verbose mode */
2698 dlt_user.verbose_mode = 0;
2703 int dlt_enable_local_print(void)
2705 if (dlt_user_initialised==0)
2713 dlt_user.enable_local_print = 1;
2718 int dlt_disable_local_print(void)
2720 if (dlt_user_initialised==0)
2728 dlt_user.enable_local_print = 0;
2733 void dlt_user_receiverthread_function(__attribute__((unused)) void *ptr)
2737 /* Check for new messages from DLT daemon */
2738 if (dlt_user_log_check_user_message()==-1)
2740 /* Critical error */
2741 dlt_log(LOG_CRIT,"Receiver thread encountered error condition\n");
2744 usleep(DLT_USER_RECEIVE_DELAY); /* delay */
2748 /* Private functions of user library */
2750 int dlt_user_log_init(DltContext *handle, DltContextData *log)
2752 if (dlt_user_initialised==0)
2760 log->handle = handle;
2765 int dlt_user_queue_resend(void)
2767 static unsigned char dlt_user_queue_resend_error_counter = 0;
2769 if(dlt_user.dlt_log_handle < 0)
2771 // Fail silenty. FIFO is not open yet
2775 * Ask segmented thread to try emptying the buffer soon.
2776 * This will be freed in dlt_user_trace_network_segmented_thread
2778 s_segmented_data *resend_data = malloc(sizeof(s_segmented_data));
2780 if (NULL == resend_data)
2785 resend_data->payload_len = DLT_DELAYED_RESEND_INDICATOR_PATTERN;
2789 /* Open queue if it is not open */
2790 if(dlt_init_message_queue() < 0)
2792 if(!dlt_user_queue_resend_error_counter)
2794 // log error only when problem occurred first time
2795 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2797 dlt_user_queue_resend_error_counter = 1;
2802 if(mq_send(dlt_user.dlt_segmented_queue_write_handle, (char *)&resend_data, sizeof(s_segmented_data *), 1) < 0)
2804 if(!dlt_user_queue_resend_error_counter)
2806 // log error only when problem occurred first time
2808 snprintf(str,254,"Could not request resending.: %s \n",strerror(errno));
2809 dlt_log(LOG_CRIT, str);
2811 dlt_user_queue_resend_error_counter = 1;
2816 dlt_user_queue_resend_error_counter = 0;
2818 //thread_data will be freed by the receiver function
2819 //coverity[leaked_storage]
2823 DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype)
2826 DltUserHeader userheader;
2829 DltReturnValue ret = DLT_RETURN_OK;
2833 return DLT_RETURN_ERROR;
2838 return DLT_RETURN_ERROR;
2841 if (dlt_user.appID[0]=='\0')
2843 return DLT_RETURN_ERROR;
2846 if (log->handle->contextID[0]=='\0')
2848 return DLT_RETURN_ERROR;
2851 if ((mtype<DLT_TYPE_LOG) || (mtype>DLT_TYPE_CONTROL))
2853 return DLT_RETURN_ERROR;
2856 /* also for Trace messages */
2857 #ifdef DLT_SHM_ENABLE
2858 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_SHM)==-1)
2860 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
2863 return DLT_RETURN_ERROR;
2866 if (dlt_message_init(&msg,0)==-1)
2868 return DLT_RETURN_ERROR;
2871 msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
2873 if (dlt_set_storageheader(msg.storageheader,dlt_user.ecuID)==-1)
2875 return DLT_RETURN_ERROR;
2878 msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
2879 msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_PROTOCOL_VERSION1 ;
2881 if (dlt_user.verbose_mode)
2883 /* In verbose mode, send extended header */
2884 msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2888 /* In non-verbose, send extended header if desired */
2889 #if (DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE==1)
2890 msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2894 #if (BYTE_ORDER==BIG_ENDIAN)
2895 msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
2898 msg.standardheader->mcnt = log->handle->mcnt++;
2900 /* Set header extra parameters */
2901 dlt_set_id(msg.headerextra.ecu,dlt_user.ecuID);
2902 //msg.headerextra.seid = 0;
2903 msg.headerextra.tmsp = dlt_uptime();
2905 if (dlt_message_set_extraparameters(&msg,0)==-1)
2907 return DLT_RETURN_ERROR;
2910 /* Fill out extended header, if extended header should be provided */
2911 if (DLT_IS_HTYP_UEH(msg.standardheader->htyp))
2913 /* with extended header */
2914 msg.extendedheader = (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp) );
2920 msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2923 case DLT_TYPE_NW_TRACE:
2925 msg.extendedheader->msin = (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT) | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2930 /* This case should not occur */
2931 return DLT_RETURN_ERROR;
2936 /* If in verbose mode, set flag in header for verbose mode */
2937 if (dlt_user.verbose_mode)
2939 msg.extendedheader->msin |= DLT_MSIN_VERB;
2942 msg.extendedheader->noar = log->args_num; /* number of arguments */
2943 dlt_set_id(msg.extendedheader->apid,dlt_user.appID); /* application id */
2944 dlt_set_id(msg.extendedheader->ctid,log->handle->contextID); /* context id */
2946 msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2950 /* without extended header */
2951 msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2954 len=msg.headersize - sizeof(DltStorageHeader) +log->size;
2957 dlt_log(LOG_CRIT,"Huge message discarded!\n");
2958 return DLT_RETURN_ERROR;
2961 msg.standardheader->len = DLT_HTOBE_16(len);
2963 /* print to std out, if enabled */
2964 if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) &&
2965 (dlt_user.local_print_mode != DLT_PM_AUTOMATIC))
2967 if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
2969 if (dlt_user_print_msg(&msg, log)==-1)
2971 return DLT_RETURN_ERROR;
2976 if (dlt_user.dlt_is_file)
2979 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size);
2984 /* Reattach to daemon if neccesary */
2985 dlt_user_log_reattach_to_daemon();
2987 if (dlt_user.overflow_counter)
2989 if (dlt_user_log_send_overflow()==0)
2991 sprintf(str,"%u messages discarded!\n",dlt_user.overflow_counter);
2992 dlt_log(LOG_ERR, str);
2993 dlt_user.overflow_counter=0;
2997 /* try to resent old data first */
2998 ret = DLT_RETURN_OK;
2999 if(dlt_user.dlt_log_handle!=-1)
3000 ret = dlt_user_log_resend_buffer();
3001 if(ret==DLT_RETURN_OK)
3003 /* resend ok or nothing to resent */
3004 #ifdef DLT_SHM_ENABLE
3005 if(dlt_user.dlt_log_handle!=-1)
3006 dlt_shm_push(&dlt_user.dlt_shm,msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3007 log->buffer, log->size,0,0);
3010 ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
3011 &(userheader), sizeof(DltUserHeader),
3016 #ifdef DLT_TEST_ENABLE
3017 if(dlt_user.corrupt_user_header) {
3018 userheader.pattern[0]=0xff;
3019 userheader.pattern[1]=0xff;
3020 userheader.pattern[2]=0xff;
3021 userheader.pattern[3]=0xff;
3023 if(dlt_user.corrupt_message_size) {
3024 msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
3027 ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
3028 &(userheader), sizeof(DltUserHeader),
3029 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3030 log->buffer, log->size);
3034 /* store message in ringbuffer, if an error has occured */
3035 if (ret!=DLT_RETURN_OK)
3039 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3040 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3041 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3042 log->buffer, log->size)==-1)
3044 if(dlt_user.overflow_counter==0)
3047 dlt_log(LOG_ERR,"Buffer full! Messages will be discarded.\n");
3049 ret = DLT_RETURN_BUFFER_FULL;
3054 // Fail silenty if FIFO is not open
3055 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3057 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_log: Failed to queue resending.\n");
3063 case DLT_RETURN_BUFFER_FULL:
3066 dlt_user.overflow_counter += 1;
3067 return DLT_RETURN_BUFFER_FULL;
3069 case DLT_RETURN_PIPE_FULL:
3071 /* data could not be written */
3072 return DLT_RETURN_PIPE_FULL;
3074 case DLT_RETURN_PIPE_ERROR:
3076 /* handle not open or pipe error */
3077 close(dlt_user.dlt_log_handle);
3078 dlt_user.dlt_log_handle = -1;
3080 #ifdef DLT_SHM_ENABLE
3081 /* free shared memory */
3082 dlt_shm_free_client(&dlt_user.dlt_shm);
3085 if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
3087 dlt_user_print_msg(&msg, log);
3090 return DLT_RETURN_PIPE_ERROR;
3092 case DLT_RETURN_ERROR:
3094 /* other error condition */
3095 return DLT_RETURN_ERROR;
3099 return DLT_RETURN_OK;
3103 /* This case should never occur. */
3104 return DLT_RETURN_ERROR;
3109 return DLT_RETURN_OK;
3112 int dlt_user_log_send_register_application(void)
3114 DltUserHeader userheader;
3115 DltUserControlMsgRegisterApplication usercontext;
3119 if (dlt_user.appID[0]=='\0')
3124 /* set userheader */
3125 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION)==-1)
3130 /* set usercontext */
3131 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3132 usercontext.pid = getpid();
3134 if (dlt_user.application_description!=0)
3136 usercontext.description_length = strlen(dlt_user.application_description);
3140 usercontext.description_length = 0;
3143 if (dlt_user.dlt_is_file)
3149 ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication),dlt_user.application_description,usercontext.description_length);
3151 /* store message in ringbuffer, if an error has occured */
3152 if (ret!=DLT_RETURN_OK)
3156 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3157 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3158 (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterApplication),
3159 (const unsigned char*)dlt_user.application_description, usercontext.description_length)==-1)
3161 dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3168 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3170 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_application: Failed to queue resending.\n");
3177 int dlt_user_log_send_unregister_application(void)
3179 DltUserHeader userheader;
3180 DltUserControlMsgUnregisterApplication usercontext;
3184 if (dlt_user.appID[0]=='\0')
3189 /* set userheader */
3190 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION)==-1)
3195 /* set usercontext */
3196 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3197 usercontext.pid = getpid();
3199 if (dlt_user.dlt_is_file)
3205 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication));
3206 return ((ret==DLT_RETURN_OK)?0:-1);
3209 int dlt_user_log_send_register_context(DltContextData *log)
3211 DltUserHeader userheader;
3212 DltUserControlMsgRegisterContext usercontext;
3225 if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3230 /* set userheader */
3231 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT)==-1)
3236 /* set usercontext */
3237 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3238 dlt_set_id(usercontext.ctid,log->handle->contextID); /* context id */
3239 usercontext.log_level_pos = log->handle->log_level_pos;
3240 usercontext.pid = getpid();
3242 usercontext.log_level = (int8_t)log->log_level;
3243 usercontext.trace_status = (int8_t)log->trace_status;
3245 if (log->context_description!=0)
3247 usercontext.description_length = strlen(log->context_description);
3251 usercontext.description_length = 0;
3254 if (dlt_user.dlt_is_file)
3260 ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext),log->context_description,usercontext.description_length);
3262 /* store message in ringbuffer, if an error has occured */
3263 if (ret!=DLT_RETURN_OK)
3267 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3268 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3269 (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterContext),
3270 (const unsigned char*)log->context_description, usercontext.description_length)==-1)
3272 dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3279 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3281 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_context: Failed to queue resending.\n");
3289 int dlt_user_log_send_unregister_context(DltContextData *log)
3291 DltUserHeader userheader;
3292 DltUserControlMsgUnregisterContext usercontext;
3305 if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3310 /* set userheader */
3311 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT)==-1)
3316 /* set usercontext */
3317 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3318 dlt_set_id(usercontext.ctid,log->handle->contextID); /* context id */
3319 usercontext.pid = getpid();
3321 if (dlt_user.dlt_is_file)
3327 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext));
3328 return ((ret==DLT_RETURN_OK)?0:-1);
3331 int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
3333 DltUserHeader userheader;
3334 DltUserControlMsgAppLogLevelTraceStatus usercontext;
3337 if ((appid==0) || (appid[0]=='\0'))
3342 /* Removed because of DltLogLevelType and DltTraceStatusType
3344 if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
3349 if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
3356 /* set userheader */
3357 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS)==-1)
3362 /* set usercontext */
3363 dlt_set_id(usercontext.apid,appid); /* application id */
3364 usercontext.log_level = loglevel;
3365 usercontext.trace_status = tracestatus;
3367 if (dlt_user.dlt_is_file)
3373 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus));
3374 return ((ret==DLT_RETURN_OK)?0:-1);
3377 int dlt_user_log_send_log_mode(DltUserLogMode mode)
3379 DltUserHeader userheader;
3380 DltUserControlMsgLogMode logmode;
3384 /* set userheader */
3385 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE)==-1)
3391 logmode.log_mode = (unsigned char) mode;
3393 if (dlt_user.dlt_is_file)
3399 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode));
3400 return ((ret==DLT_RETURN_OK)?0:-1);
3403 int dlt_user_print_msg(DltMessage *msg, DltContextData *log)
3405 uint8_t *databuffer_tmp;
3406 int32_t datasize_tmp;
3407 int32_t databuffersize_tmp;
3408 static char text[DLT_USER_TEXT_LENGTH];
3410 if ((msg==0) || (log==0))
3415 /* Save variables before print */
3416 databuffer_tmp = msg->databuffer;
3417 datasize_tmp = msg->datasize;
3418 databuffersize_tmp = msg->databuffersize;
3420 /* Act like a receiver, convert header back to host format */
3421 msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len);
3422 dlt_message_get_extraparameters(msg,0);
3424 msg->databuffer = log->buffer;
3425 msg->datasize = log->size;
3426 msg->databuffersize = log->size;
3428 /* Print message as ASCII */
3429 if (dlt_message_print_ascii(msg,text,DLT_USER_TEXT_LENGTH,0)==-1)
3434 /* Restore variables and set len to BE*/
3435 msg->databuffer = databuffer_tmp;
3436 msg->databuffersize = databuffersize_tmp;
3437 msg->datasize = datasize_tmp;
3439 msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
3444 int dlt_user_log_check_user_message(void)
3451 DltUserHeader *userheader;
3452 DltReceiver *receiver = &(dlt_user.receiver);
3454 DltUserControlMsgLogLevel *usercontextll;
3455 DltUserControlMsgInjection *usercontextinj;
3456 DltUserControlMsgLogState *userlogstate;
3457 unsigned char *userbuffer;
3459 /* For delayed calling of injection callback, to avoid deadlock */
3460 DltUserInjectionCallback delayed_injection_callback;
3461 unsigned char *delayed_inject_buffer = 0;
3462 uint32_t delayed_inject_data_length = 0;
3464 /* Ensure that callback is null before searching for it */
3465 delayed_injection_callback.injection_callback = 0;
3466 delayed_injection_callback.service_id = 0;
3468 if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
3472 if (dlt_receiver_receive_fd(receiver)<=0)
3474 /* No new message available */
3478 /* look through buffer as long as data is in there */
3481 if (receiver->bytesRcvd < (int32_t)sizeof(DltUserHeader))
3486 /* resync if necessary */
3490 userheader = (DltUserHeader*) (receiver->buf+offset);
3492 /* Check for user header pattern */
3493 if (dlt_user_check_userheader(userheader))
3500 while ((int32_t)(sizeof(DltUserHeader)+offset)<=receiver->bytesRcvd);
3502 /* Check for user header pattern */
3503 if (dlt_user_check_userheader(userheader)<0 ||
3504 dlt_user_check_userheader(userheader)==0)
3509 /* Set new start offset */
3512 receiver->buf+=offset;
3513 receiver->bytesRcvd-=offset;
3516 switch (userheader->message)
3518 case DLT_USER_MESSAGE_LOG_LEVEL:
3520 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel)))
3526 usercontextll = (DltUserControlMsgLogLevel*) (receiver->buf+sizeof(DltUserHeader));
3528 /* Update log level and trace status */
3529 if (usercontextll!=0)
3533 if ((usercontextll->log_level_pos >= 0) && (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries))
3535 // printf("Store ll, ts\n");
3536 if (dlt_user.dlt_ll_ts)
3538 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = usercontextll->log_level;
3539 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status = usercontextll->trace_status;
3540 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr)
3541 *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) = usercontextll->log_level;
3542 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr)
3543 *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) = usercontextll->trace_status;
3550 /* keep not read data in buffer */
3551 if (dlt_receiver_remove(receiver,sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel))==-1)
3557 case DLT_USER_MESSAGE_INJECTION:
3559 /* At least, user header, user context, and service id and data_length of injected message is available */
3560 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)))
3566 usercontextinj = (DltUserControlMsgInjection*) (receiver->buf+sizeof(DltUserHeader));
3567 userbuffer = (unsigned char*) (receiver->buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection));
3572 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))
3580 if ((usercontextinj->data_length_inject>0) && (dlt_user.dlt_ll_ts))
3582 /* Check if injection callback is registered for this context */
3583 for (i=0; i<dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks;i++)
3585 if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) &&
3586 (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id == usercontextinj->service_id))
3588 /* Prepare delayed injection callback call */
3589 if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback!=0)
3591 delayed_injection_callback.injection_callback = dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback;
3592 delayed_injection_callback.service_id = usercontextinj->service_id;
3593 delayed_inject_data_length = usercontextinj->data_length_inject;
3594 delayed_inject_buffer = malloc(delayed_inject_data_length);
3595 if(delayed_inject_buffer != 0) {
3596 memcpy(delayed_inject_buffer, userbuffer, delayed_inject_data_length);
3607 /* Delayed injection callback call */
3608 if(delayed_inject_buffer != 0 && delayed_injection_callback.injection_callback != 0) {
3609 delayed_injection_callback.injection_callback(delayed_injection_callback.service_id, delayed_inject_buffer, delayed_inject_data_length);
3610 delayed_injection_callback.injection_callback = 0;
3611 free(delayed_inject_buffer);
3612 delayed_inject_buffer = NULL;
3616 /* keep not read data in buffer */
3617 if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))==-1)
3624 case DLT_USER_MESSAGE_LOG_STATE:
3626 /* At least, user header, user context, and service id and data_length of injected message is available */
3627 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))
3633 userlogstate = (DltUserControlMsgLogState*) (receiver->buf+sizeof(DltUserHeader));
3634 dlt_user.log_state = userlogstate->log_state;
3636 /* keep not read data in buffer */
3637 if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))==-1)
3645 dlt_log(LOG_ERR,"Invalid user message type received!\n");
3647 dlt_receiver_remove(receiver,sizeof(DltUserHeader));
3648 /* In next invocation of while loop, a resync will be triggered if additional data was received */
3661 if (dlt_receiver_move_to_begin(receiver)==-1)
3665 } /* while receive */
3668 return DLT_RETURN_OK;
3671 int dlt_user_log_resend_buffer(void)
3677 /* Send content of ringbuffer */
3679 count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
3682 for (num=0;num<count;num++)
3686 size = dlt_buffer_copy(&(dlt_user.startup_buffer),dlt_user.resend_buffer,sizeof(dlt_user.resend_buffer));
3690 #ifdef DLT_SHM_ENABLE
3691 dlt_shm_push(&dlt_user.dlt_shm,dlt_user.resend_buffer+sizeof(DltUserHeader),size-sizeof(DltUserHeader),0,0,0,0);
3694 ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,sizeof(DltUserHeader),0,0,0,0);
3697 ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,size,0,0,0,0);
3700 /* in case of error, keep message in ringbuffer */
3701 if (ret==DLT_RETURN_OK)
3703 dlt_buffer_remove(&(dlt_user.startup_buffer));
3707 /* keep message in ringbuffer */
3718 void dlt_user_log_reattach_to_daemon(void)
3720 uint32_t num,reregistered=0;
3723 DltContextData log_new;
3725 if (dlt_user.dlt_log_handle<0)
3727 dlt_user.dlt_log_handle=-1;
3729 /* try to open pipe to dlt daemon */
3730 dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK);
3731 if (dlt_user.dlt_log_handle > 0)
3733 if (dlt_user_log_init(&handle,&log_new)==-1)
3738 #ifdef DLT_SHM_ENABLE
3739 /* init shared memory */
3740 if (dlt_shm_init_client(&dlt_user.dlt_shm,DLT_SHM_KEY) < 0)
3742 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
3743 dlt_log(LOG_WARNING, str);
3748 dlt_log(LOG_NOTICE, "Logging re-enabled!\n");
3750 /* Re-register application */
3751 if (dlt_user_log_send_register_application()==-1)
3758 /* Re-register all stored contexts */
3759 for (num=0; num<dlt_user.dlt_ll_ts_num_entries; num++)
3761 /* Re-register stored context */
3762 if ((dlt_user.appID[0]!='\0') && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID[0]!='\0'))
3764 //dlt_set_id(log_new.appID, dlt_user.appID);
3765 dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
3766 handle.log_level_pos = num;
3767 log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
3769 log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
3770 log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
3772 if (dlt_user_log_send_register_context(&log_new)==-1)
3784 if (reregistered==1)
3786 dlt_user_log_resend_buffer();
3792 int dlt_user_log_send_overflow(void)
3794 DltUserHeader userheader;
3795 DltUserControlMsgBufferOverflow userpayload;
3798 /* set userheader */
3799 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW)==-1)
3804 if (dlt_user.dlt_is_file)
3809 /* set user message parameters */
3810 userpayload.overflow_counter = dlt_user.overflow_counter;
3811 dlt_set_id(userpayload.apid,dlt_user.appID);
3814 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader),
3815 &(userpayload), sizeof(DltUserControlMsgBufferOverflow));
3816 return ((ret==DLT_RETURN_OK)?0:-1);
3819 int dlt_user_check_buffer(int *total_size, int *used_size)
3821 #ifdef DLT_SHM_ENABLE
3822 *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm));
3823 *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm));
3825 *total_size = dlt_buffer_get_total_size(&(dlt_user.startup_buffer));
3826 *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer));
3832 #ifdef DLT_TEST_ENABLE
3833 void dlt_user_test_corrupt_user_header(int enable)
3835 dlt_user.corrupt_user_header = enable;
3837 void dlt_user_test_corrupt_message_size(int enable,int16_t size)
3839 dlt_user.corrupt_message_size = enable;
3840 dlt_user.corrupt_message_size_size = size;