3 * Copyright (C) 2012-2014 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/.
17 * Alexander Wenzel <alexander.aw.wenzel@bmw.de>
18 * Markus Klein <Markus.Klein@esk.fraunhofer.de>
19 * Mikko Rapeli <mikko.rapeli@bmw.de>
22 * For further information see http://www.genivi.org/.
26 #include <stdlib.h> /* for getenv(), free(), atexit() */
27 #include <string.h> /* for strcmp(), strncmp(), strlen(), memset(), memcpy() */
28 #include <signal.h> /* for signal(), SIGPIPE, SIG_IGN */
30 #if !defined (__WIN32__)
31 #include <syslog.h> /* for LOG_... */
32 #include <semaphore.h>
33 #include <pthread.h> /* POSIX Threads */
43 #include <sys/uio.h> /* writev() */
47 #include <sys/prctl.h>
51 #include "dlt_user_shared.h"
52 #include "dlt_user_shared_cfg.h"
53 #include "dlt_user_cfg.h"
55 static DltUser dlt_user;
56 static int dlt_user_initialised = 0;
57 static int dlt_user_freeing = 0;
59 static char str[DLT_USER_BUFFER_LENGTH];
61 static sem_t dlt_mutex;
62 static pthread_t dlt_receiverthread_handle;
63 static pthread_attr_t dlt_receiverthread_attr;
65 /* Segmented Network Trace */
66 #define DLT_MAX_TRACE_SEGMENT_SIZE 1024
67 #define DLT_MESSAGE_QUEUE_NAME "/dlt_message_queue"
68 #define DLT_DELAYED_RESEND_INDICATOR_PATTERN 0xFFFF
70 /* Mutex to wait on while message queue is not initialized */
71 pthread_mutex_t mq_mutex;
72 pthread_cond_t mq_init_condition;
74 /* Structure to pass data to segmented thread */
78 DltNetworkTraceType nw_trace_type;
85 /* Function prototypes for internally used functions */
86 static void dlt_user_receiverthread_function(void *ptr);
87 static void dlt_user_atexit_handler(void);
88 static int dlt_user_log_init(DltContext *handle, DltContextData *log);
89 static DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype);
90 static int dlt_user_log_send_register_application(void);
91 static int dlt_user_log_send_unregister_application(void);
92 static int dlt_user_log_send_register_context(DltContextData *log);
93 static int dlt_user_log_send_unregister_context(DltContextData *log);
94 static int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus);
95 static int dlt_user_log_send_log_mode(DltUserLogMode mode);
96 static int dlt_user_print_msg(DltMessage *msg, DltContextData *log);
97 static int dlt_user_log_check_user_message(void);
98 static void dlt_user_log_reattach_to_daemon(void);
99 static int dlt_user_log_send_overflow(void);
100 static void dlt_user_trace_network_segmented_thread(void *unused);
101 static void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data);
102 static int dlt_user_queue_resend(void);
104 int dlt_user_check_library_version(const char *user_major_version,const char *user_minor_version){
107 char lib_major_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
108 char lib_minor_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
110 dlt_get_major_version( lib_major_version);
111 dlt_get_minor_version( lib_minor_version);
113 if( (strcmp(lib_major_version,user_major_version)!=0) || (strcmp(lib_minor_version,user_minor_version)!=0))
115 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);
116 dlt_log(LOG_WARNING, str);
124 char filename[DLT_USER_MAX_FILENAME_LENGTH];
127 // process is exiting. Do not allocate new resources.
128 if (dlt_user_freeing != 0)
130 // return negative value, to stop the current log
134 // WARNING: multithread unsafe !
135 // Another thread will check that dlt_user_initialised != 0, but the lib is not initialised !
136 dlt_user_initialised = 1;
138 /* Initialize common part of dlt_init()/dlt_init_file() */
139 if (dlt_init_common()==-1)
141 dlt_user_initialised = 0;
145 /* check environment variables */
148 dlt_user.dlt_is_file = 0;
149 dlt_user.overflow = 0;
150 dlt_user.overflow_counter = 0;
151 #ifdef DLT_SHM_ENABLE
152 memset(&(dlt_user.dlt_shm),0,sizeof(DltShm));
155 /* create and open DLT user FIFO */
156 sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
158 /* Try to delete existing pipe, ignore result of unlink */
161 ret=mkfifo(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP );
164 sprintf(str,"Loging disabled, FIFO user %s cannot be created!\n",filename);
165 dlt_log(LOG_WARNING, str);
166 /* return 0; */ /* removed to prevent error, when FIFO already exists */
169 // S_IWGRP cannot be set by mkfifo (???), let's reassign right bits
170 ret=chmod(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP );
173 sprintf(str,"FIFO user %s cannot be chmoded!\n", DLT_USER_DIR);
174 dlt_log(LOG_ERR, str);
178 dlt_user.dlt_user_handle = open(filename, O_RDWR | O_CLOEXEC);
179 if (dlt_user.dlt_user_handle == DLT_FD_INIT)
181 sprintf(str,"Loging disabled, FIFO user %s cannot be opened!\n",filename);
182 dlt_log(LOG_WARNING, str);
187 /* open DLT output FIFO */
188 dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK | O_CLOEXEC );
189 if (dlt_user.dlt_log_handle==-1)
191 sprintf(str,"Loging disabled, FIFO %s cannot be opened with open()!\n",DLT_USER_FIFO);
192 dlt_log(LOG_WARNING, str);
197 #ifdef DLT_SHM_ENABLE
198 /* init shared memory */
199 if (dlt_shm_init_client(&(dlt_user.dlt_shm),DLT_SHM_KEY) < 0)
201 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
202 dlt_log(LOG_WARNING, str);
209 if (dlt_receiver_init(&(dlt_user.receiver),dlt_user.dlt_user_handle, DLT_USER_RCVBUF_MAX_SIZE)==-1)
211 dlt_user_initialised = 0;
215 /* Start receiver thread */
216 if (pthread_create(&(dlt_receiverthread_handle),
218 (void *) &dlt_user_receiverthread_function,
221 if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
223 dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
226 dlt_log(LOG_CRIT, "Can't create receiver thread!\n");
227 dlt_user_initialised = 0;
231 if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
233 dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
236 /* These will be lazy initialized only when needed */
237 dlt_user.dlt_segmented_queue_read_handle = -1;
238 dlt_user.dlt_segmented_queue_write_handle = -1;
240 /* Wait mutext for segmented thread */
241 pthread_mutex_init(&mq_mutex, NULL);
242 pthread_cond_init(&mq_init_condition, NULL);
244 /* Start the segmented thread */
245 if(pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL,
246 (void *)dlt_user_trace_network_segmented_thread, NULL))
248 dlt_log(LOG_CRIT, "Can't start segmented thread!\n");
255 int dlt_init_file(const char *name)
257 dlt_user_initialised = 1;
259 /* Initialize common part of dlt_init()/dlt_init_file() */
260 if (dlt_init_common()==-1)
262 dlt_user_initialised = 0;
266 dlt_user.dlt_is_file = 1;
268 /* open DLT output file */
269 dlt_user.dlt_log_handle = open(name,O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
270 if (dlt_user.dlt_log_handle == -1)
272 sprintf(str,"Log file %s cannot be opened!\n",name);
273 dlt_log(LOG_ERR, str);
280 int dlt_init_message_queue(void)
282 pthread_mutex_lock(&mq_mutex);
283 if(dlt_user.dlt_segmented_queue_read_handle >= 0 &&
284 dlt_user.dlt_segmented_queue_write_handle >= 0)
286 // Already intialized
287 pthread_mutex_unlock(&mq_mutex);
291 /* Generate per process name for queue */
292 char queue_name[NAME_MAX];
293 sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
295 /* Maximum queue size is 10, limit to size of pointers */
296 struct mq_attr mqatr;
298 mqatr.mq_maxmsg = 10;
299 mqatr.mq_msgsize = sizeof(s_segmented_data *);
300 mqatr.mq_curmsgs = 0;
303 * Create the message queue. It must be newly created
304 * if old one was left by a crashing process.
306 dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
307 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
308 if(dlt_user.dlt_segmented_queue_read_handle < 0)
312 dlt_log(LOG_WARNING, "Old message queue exists, trying to delete.\n");
313 if(mq_unlink(queue_name) < 0)
316 snprintf(str,255,"Could not delete existing message queue!: %s \n",strerror(errno));
317 dlt_log(LOG_CRIT, str);
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);
325 if(dlt_user.dlt_segmented_queue_read_handle < 0)
328 snprintf(str,255,"Can't create message queue read handle!: %s \n",strerror(errno));
329 dlt_log(LOG_CRIT, str);
330 pthread_mutex_unlock(&mq_mutex);
335 dlt_user.dlt_segmented_queue_write_handle = mq_open(queue_name, O_WRONLY|O_NONBLOCK);
336 if(dlt_user.dlt_segmented_queue_write_handle < 0)
340 snprintf(str,255,"Can't open message queue write handle!: %s \n",strerror(errno));
341 dlt_log(LOG_CRIT, str);
342 pthread_mutex_unlock(&mq_mutex);
346 pthread_cond_signal(&mq_init_condition);
347 pthread_mutex_unlock(&mq_mutex);
351 int dlt_init_common(void)
353 char *env_local_print;
355 /* Binary semaphore for threads */
356 if (sem_init(&dlt_mutex, 0, 1)==-1)
358 dlt_user_initialised = 0;
362 /* set to unknown state of connected client */
363 dlt_user.log_state = -1;
365 dlt_user.dlt_log_handle=-1;
366 dlt_user.dlt_user_handle=DLT_FD_INIT;
368 dlt_set_id(dlt_user.ecuID,DLT_USER_DEFAULT_ECU_ID);
369 dlt_set_id(dlt_user.appID,"");
371 dlt_user.application_description = 0;
373 /* Verbose mode is enabled by default */
374 dlt_user.verbose_mode = 1;
376 /* Local print is disabled by default */
377 dlt_user.enable_local_print = 0;
379 dlt_user.local_print_mode = DLT_PM_UNSET;
381 env_local_print = getenv(DLT_USER_ENV_LOCAL_PRINT_MODE);
384 if (strcmp(env_local_print,"AUTOMATIC")==0)
386 dlt_user.local_print_mode = DLT_PM_AUTOMATIC;
388 else if (strcmp(env_local_print,"FORCE_ON")==0)
390 dlt_user.local_print_mode = DLT_PM_FORCE_ON;
392 else if (strcmp(env_local_print,"FORCE_OFF")==0)
394 dlt_user.local_print_mode = DLT_PM_FORCE_OFF;
398 /* Initialize LogLevel/TraceStatus field */
400 dlt_user.dlt_ll_ts = 0;
401 dlt_user.dlt_ll_ts_max_num_entries = 0;
402 dlt_user.dlt_ll_ts_num_entries = 0;
404 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)
406 dlt_user_initialised = 0;
412 signal(SIGPIPE,SIG_IGN); /* ignore pipe signals */
414 atexit(dlt_user_atexit_handler);
416 #ifdef DLT_TEST_ENABLE
417 dlt_user.corrupt_user_header = 0;
418 dlt_user.corrupt_message_size = 0;
419 dlt_user.corrupt_message_size_size = 0;
425 void dlt_user_atexit_handler(void)
427 if (dlt_user_initialised==0)
429 dlt_log(LOG_WARNING, "dlt_user_atexit_handler dlt_user_initialised==0\n");
435 /* Try to resend potential log messages in the user buffer */
436 int count = dlt_user_atexit_blow_out_user_buffer();
440 sprintf(tmp,"Lost log messages in user buffer when exiting: %i\n",count);
441 dlt_log(LOG_ERR, tmp);
444 /* Unregister app (this also unregisters all contexts in daemon) */
445 /* Ignore return value */
446 dlt_unregister_app();
449 /* Ignore return value */
453 int dlt_user_atexit_blow_out_user_buffer(void){
457 uint32_t exitTime = dlt_uptime() + DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT;
459 while(dlt_uptime() < exitTime ){
461 ret = dlt_user_log_resend_buffer();
468 usleep(DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP);
472 count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
481 char filename[DLT_USER_MAX_FILENAME_LENGTH];
483 if( dlt_user_freeing != 0 )
484 // resources are already being freed. Do nothing and return.
487 // library is freeing its resources. Avoid to allocate it in dlt_init()
488 dlt_user_freeing = 1;
490 if (dlt_user_initialised==0)
492 dlt_user_freeing = 0;
495 dlt_user_initialised = 0;
497 if (dlt_receiverthread_handle)
499 /* Ignore return value */
500 pthread_cancel(dlt_receiverthread_handle);
503 if (dlt_user.dlt_segmented_nwt_handle)
505 pthread_cancel(dlt_user.dlt_segmented_nwt_handle);
508 if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
510 sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
512 close(dlt_user.dlt_user_handle);
513 dlt_user.dlt_user_handle=DLT_FD_INIT;
518 #ifdef DLT_SHM_ENABLE
519 /* free shared memory */
520 dlt_shm_free_client(&dlt_user.dlt_shm);
523 if (dlt_user.dlt_log_handle!=-1)
525 /* close log file/output fifo to daemon */
526 close(dlt_user.dlt_log_handle);
527 dlt_user.dlt_log_handle = -1;
530 /* Ignore return value */
532 dlt_receiver_free(&(dlt_user.receiver));
535 /* Ignore return value */
537 dlt_buffer_free_dynamic(&(dlt_user.startup_buffer));
541 if (dlt_user.dlt_ll_ts)
543 for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
545 if (dlt_user.dlt_ll_ts[i].injection_table!=0)
547 free(dlt_user.dlt_ll_ts[i].injection_table);
548 dlt_user.dlt_ll_ts[i].injection_table = 0;
550 dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
553 free(dlt_user.dlt_ll_ts);
554 dlt_user.dlt_ll_ts = 0;
555 dlt_user.dlt_ll_ts_max_num_entries = 0;
556 dlt_user.dlt_ll_ts_num_entries = 0;
560 char queue_name[NAME_MAX];
561 sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
564 * Ignore errors from these, to not to spam user if dlt_free
565 * is accidentally called multiple times.
567 mq_close(dlt_user.dlt_segmented_queue_write_handle);
568 mq_close(dlt_user.dlt_segmented_queue_read_handle);
569 mq_unlink(queue_name);
571 // allow the user app to do dlt_init() again.
572 // The flag is unset only to keep almost the same behaviour as before, on EntryNav
573 // This should be removed for other projects (see documentation of dlt_free()
574 dlt_user_freeing = 0;
579 int dlt_check_library_version(const char * user_major_version,const char * user_minor_version)
581 return dlt_user_check_library_version(user_major_version, user_minor_version);
584 int dlt_register_app(const char *appid, const char * description)
588 if (dlt_user_initialised==0)
596 if ((appid==0) || (appid[0]=='\0'))
601 /* check if application already registered */
602 /* if yes do not register again */
605 if(appid[0]==dlt_user.appID[0])
610 if(appid[0]==dlt_user.appID[0] &&
611 appid[1]==dlt_user.appID[1])
616 if(appid[0]==dlt_user.appID[0] &&
617 appid[1]==dlt_user.appID[1] &&
618 appid[2]==dlt_user.appID[2])
623 if(appid[0]==dlt_user.appID[0] &&
624 appid[1]==dlt_user.appID[1] &&
625 appid[2]==dlt_user.appID[2] &&
626 appid[3]==dlt_user.appID[3])
632 /* Store locally application id and application description */
633 dlt_set_id(dlt_user.appID, appid);
635 if (dlt_user.application_description!=0)
637 free(dlt_user.application_description);
640 dlt_user.application_description = 0;
644 size_t desc_len = strlen(description);
645 dlt_user.application_description= malloc(desc_len+1);
646 if (dlt_user.application_description){
647 strncpy(dlt_user.application_description, description, desc_len);
649 /* Terminate transmitted string with 0 */
650 dlt_user.application_description[desc_len]='\0';
661 ret = dlt_user_log_send_register_application();
665 int dlt_register_context(DltContext *handle, const char *contextid, const char * description)
667 if (dlt_user_initialised==0)
677 if (dlt_user.appID[0]=='\0')
679 dlt_log(LOG_ERR, "no application registered!\n");
685 if ((contextid==0) || (contextid[0]=='\0'))
693 return dlt_register_context_ll_ts(handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET);
696 int dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const char * description, int loglevel, int tracestatus)
701 if (dlt_user_initialised==0)
711 if (dlt_user.appID[0]=='\0')
713 dlt_log(LOG_ERR, "no application registered!\n");
721 if ((contextid==0) || (contextid[0]=='\0'))
726 if ((loglevel<DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel>DLT_LOG_VERBOSE) || (loglevel==DLT_LOG_DEFAULT))
731 if ((tracestatus<DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus>DLT_TRACE_STATUS_ON) || (tracestatus==DLT_TRACE_STATUS_DEFAULT))
736 if (dlt_user_log_init(handle, &log)==-1)
741 /* Reset message counter */
744 /* Store context id in log level/trace status field */
746 /* Check if already registered, else register context */
749 /* Check of double context registration removed */
750 /* Double registration is already checked by daemon */
752 /* Allocate or expand context array */
753 if (dlt_user.dlt_ll_ts == 0)
755 dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*DLT_USER_CONTEXT_ALLOC_SIZE);
756 if (dlt_user.dlt_ll_ts==0)
762 dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE;
764 /* Initialize new entries */
765 for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
767 dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
769 /* At startup, logging and tracing is locally enabled */
770 /* the correct log level/status is set after received from daemon */
771 dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
772 dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
774 dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
775 dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
777 dlt_user.dlt_ll_ts[i].context_description = 0;
779 dlt_user.dlt_ll_ts[i].injection_table = 0;
780 dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
785 if ((dlt_user.dlt_ll_ts_num_entries%DLT_USER_CONTEXT_ALLOC_SIZE)==0)
787 /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
788 dlt_ll_ts_type *old_ll_ts;
789 uint32_t old_max_entries;
791 old_ll_ts = dlt_user.dlt_ll_ts;
792 old_max_entries = dlt_user.dlt_ll_ts_max_num_entries;
794 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;
795 dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*
796 dlt_user.dlt_ll_ts_max_num_entries);
797 if (dlt_user.dlt_ll_ts==0)
799 dlt_user.dlt_ll_ts = old_ll_ts;
800 dlt_user.dlt_ll_ts_max_num_entries = old_max_entries;
805 memcpy(dlt_user.dlt_ll_ts,old_ll_ts,sizeof(dlt_ll_ts_type)*dlt_user.dlt_ll_ts_num_entries);
808 /* Initialize new entries */
809 for (i=dlt_user.dlt_ll_ts_num_entries;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
811 dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
813 /* At startup, logging and tracing is locally enabled */
814 /* the correct log level/status is set after received from daemon */
815 dlt_user.dlt_ll_ts[i].log_level = DLT_USER_INITIAL_LOG_LEVEL;
816 dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
818 dlt_user.dlt_ll_ts[i].log_level_ptr = 0;
819 dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
821 dlt_user.dlt_ll_ts[i].context_description = 0;
823 dlt_user.dlt_ll_ts[i].injection_table = 0;
824 dlt_user.dlt_ll_ts[i].nrcallbacks = 0;
829 /* Store locally context id and context description */
830 dlt_set_id(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].contextID, contextid);
832 if (dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description!=0)
834 free(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description);
837 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = 0;
841 size_t desc_len = strlen(description);
842 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = malloc(desc_len+1);
843 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description == 0)
849 strncpy(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description, description, desc_len);
851 /* Terminate transmitted string with 0 */
852 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description[desc_len]='\0';
855 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
857 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr = malloc(sizeof(int8_t));
858 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
864 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
866 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr = malloc(sizeof(int8_t));
867 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
874 if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
876 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = loglevel;
879 if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
881 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
884 /* Prepare transfer struct */
885 //dlt_set_id(log->appID, dlt_user.appID);
886 dlt_set_id(handle->contextID, contextid);
887 handle->log_level_pos = dlt_user.dlt_ll_ts_num_entries;
889 handle->log_level_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr;
890 handle->trace_status_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr;
892 log.context_description = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description;
894 *(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;
895 *(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;
897 if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
899 log.log_level = loglevel;
903 log.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
906 if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
908 log.trace_status = tracestatus;
912 log.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
915 dlt_user.dlt_ll_ts_num_entries++;
919 return dlt_user_log_send_register_context(&log);
922 int dlt_unregister_app(void)
926 if (dlt_user_initialised==0)
931 /* Inform daemon to unregister application and all of its contexts */
932 ret = dlt_user_log_send_unregister_application();
936 /* Clear and free local stored application information */
937 dlt_set_id(dlt_user.appID, "");
939 if (dlt_user.application_description!=0)
941 free(dlt_user.application_description);
944 dlt_user.application_description = 0;
951 int dlt_unregister_context(DltContext *handle)
956 if (dlt_user_initialised==0)
961 if (dlt_user_log_init(handle, &log) == -1)
968 handle->log_level_ptr = 0;
969 handle->trace_status_ptr = 0;
971 if (dlt_user.dlt_ll_ts)
973 /* Clear and free local stored context information */
974 dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, "");
976 dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
977 dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
979 if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description!=0)
981 free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
984 if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr!=0)
986 free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr);
987 dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = 0;
990 if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr!=0)
992 free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr);
993 dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = 0;
996 dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = 0;
998 if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table)
1000 free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
1001 dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = 0;
1004 dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks = 0;
1009 /* Inform daemon to unregister context */
1010 ret = dlt_user_log_send_unregister_context(&log);
1015 int dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus)
1020 if (dlt_user_initialised==0)
1028 /* Removed because of DltLogLevelType and DltTraceStatusType
1030 if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
1035 if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
1040 if (dlt_user.dlt_ll_ts==0)
1048 if (dlt_user.dlt_ll_ts==0)
1054 /* Update local structures */
1055 for (i=0; i<dlt_user.dlt_ll_ts_num_entries;i++)
1057 dlt_user.dlt_ll_ts[i].log_level = loglevel;
1058 dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
1059 if(dlt_user.dlt_ll_ts[i].log_level_ptr)
1060 *(dlt_user.dlt_ll_ts[i].log_level_ptr) = loglevel;
1061 if(dlt_user.dlt_ll_ts[i].trace_status_ptr)
1062 *(dlt_user.dlt_ll_ts[i].trace_status_ptr) = tracestatus;
1067 /* Inform DLT server about update */
1068 ret = dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus);
1073 int dlt_get_log_state()
1075 return dlt_user.log_state;
1078 int dlt_set_log_mode(DltUserLogMode mode)
1080 if (dlt_user_initialised==0)
1088 return dlt_user_log_send_log_mode(mode);
1091 int dlt_forward_msg(void *msgdata,size_t size)
1093 DltUserHeader userheader;
1096 if ((msgdata==0) || (size==0))
1101 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
1103 /* Type of internal user message; same value for Trace messages */
1107 if (dlt_user.dlt_is_file)
1110 ret = dlt_user_log_out2(dlt_user.dlt_log_handle, msgdata, size, 0, 0);
1111 return ((ret==DLT_RETURN_OK)?0:-1);
1115 /* Reattach to daemon if neccesary */
1116 dlt_user_log_reattach_to_daemon();
1118 if (dlt_user.overflow_counter)
1120 if (dlt_user_log_send_overflow()==0)
1122 sprintf(str,"Buffer full! %u messages discarded!\n",dlt_user.overflow_counter);
1123 dlt_log(LOG_ERR, str);
1124 dlt_user.overflow_counter=0; }
1128 ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
1129 &(userheader), sizeof(DltUserHeader),
1130 msgdata, size, 0, 0);
1132 /* store message in ringbuffer, if an error has occured */
1133 if (ret!=DLT_RETURN_OK)
1137 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
1138 (unsigned char *)&(userheader), sizeof(DltUserHeader),
1139 msgdata, size, 0, 0)==-1)
1141 if(dlt_user.overflow_counter==0)
1143 dlt_log(LOG_ERR,"Buffer full! First message discarded!\n");
1145 ret = DLT_RETURN_BUFFER_FULL;
1150 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
1152 ;//dlt_log(LOG_WARNING, "dlt_forward_msg: Failed to queue resending.\n");
1158 case DLT_RETURN_BUFFER_FULL:
1161 dlt_user.overflow_counter += 1;
1164 case DLT_RETURN_PIPE_FULL:
1166 /* data could not be written */
1169 case DLT_RETURN_PIPE_ERROR:
1171 /* handle not open or pipe error */
1172 close(dlt_user.dlt_log_handle);
1173 dlt_user.dlt_log_handle = -1;
1177 case DLT_RETURN_ERROR:
1179 /* other error condition */
1188 /* This case should not occur */
1197 /* ********************************************************************************************* */
1199 inline int dlt_user_log_write_start(DltContext *handle, DltContextData *log,DltLogLevelType loglevel)
1201 return dlt_user_log_write_start_id(handle,log,loglevel,DLT_USER_DEFAULT_MSGID);
1204 int dlt_user_log_write_start_id(DltContext *handle, DltContextData *log,DltLogLevelType loglevel, uint32_t messageid)
1206 if(dlt_user_initialised==0)
1218 if (dlt_user_log_init(handle, log)==-1)
1223 if (dlt_user.dlt_ll_ts==0)
1228 if (handle->log_level_ptr && (loglevel<=(int)*(handle->log_level_ptr) ) && (loglevel!=0))
1231 log->log_level = loglevel;
1233 /* In non-verbose mode, insert message id */
1234 if (dlt_user.verbose_mode==0)
1236 if ((sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1240 /* Write message id */
1241 memcpy(log->buffer,&(messageid),sizeof(uint32_t));
1242 log->size = sizeof(uint32_t);
1244 /* as the message id is part of each message in non-verbose mode,
1245 it doesn't increment the argument counter in extended header (if used) */
1254 int dlt_user_log_write_finish(DltContextData *log)
1261 return dlt_user_log_send_log(log, DLT_TYPE_LOG) < 0 ? -1 : 0;
1264 int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length)
1274 if ((log->size+length+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1279 if (dlt_user.verbose_mode)
1281 if ((log->size+length+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1286 /* Transmit type information */
1287 type_info = DLT_TYPE_INFO_RAWD;
1289 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1290 log->size += sizeof(uint32_t);
1294 /* First transmit length of raw data, then the raw data itself */
1295 arg_size = (uint16_t)length;
1297 memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1298 log->size += sizeof(uint16_t);
1300 memcpy((log->buffer)+log->size,data,arg_size);
1301 log->size += arg_size;
1308 int dlt_user_log_write_float32(DltContextData *log, float32_t data)
1317 if (sizeof(float32_t)!=4)
1322 if ((log->size+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1327 if (dlt_user.verbose_mode)
1329 if ((log->size+sizeof(uint32_t)+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1334 type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
1336 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1337 log->size += sizeof(uint32_t);
1340 memcpy((log->buffer)+log->size,&data, sizeof(float32_t));
1341 log->size += sizeof(float32_t);
1348 int dlt_user_log_write_float64(DltContextData *log, float64_t data)
1357 if (sizeof(float64_t)!=8)
1362 if ((log->size+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1367 if (dlt_user.verbose_mode)
1369 if ((log->size+sizeof(uint32_t)+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1374 type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
1376 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1377 log->size += sizeof(uint32_t);
1380 memcpy((log->buffer)+log->size,&data, sizeof(float64_t));
1381 log->size += sizeof(float64_t);
1388 int dlt_user_log_write_uint( DltContextData *log, unsigned int data)
1395 switch (sizeof(unsigned int))
1399 return dlt_user_log_write_uint8(log, (uint8_t)data);
1404 return dlt_user_log_write_uint16(log, (uint16_t)data);
1409 return dlt_user_log_write_uint32(log, (uint32_t)data);
1414 return dlt_user_log_write_uint64(log, (uint64_t)data);
1427 int dlt_user_log_write_uint8(DltContextData *log, uint8_t data)
1436 if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1441 if (dlt_user.verbose_mode)
1443 if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1448 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
1450 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1451 log->size += sizeof(uint32_t);
1454 memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1455 log->size += sizeof(uint8_t);
1462 int dlt_user_log_write_uint16(DltContextData *log, uint16_t data)
1471 if ((log->size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1476 if (dlt_user.verbose_mode)
1478 if ((log->size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1483 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
1485 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1486 log->size += sizeof(uint32_t);
1489 memcpy((log->buffer)+log->size,&data,sizeof(uint16_t));
1490 log->size += sizeof(uint16_t);
1497 int dlt_user_log_write_uint32(DltContextData *log, uint32_t data)
1506 if ((log->size+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1511 if (dlt_user.verbose_mode)
1513 if ((log->size+sizeof(uint32_t)+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1518 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
1520 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1521 log->size += sizeof(uint32_t);
1524 memcpy((log->buffer)+log->size,&data, sizeof(uint32_t));
1525 log->size += sizeof(uint32_t);
1532 int dlt_user_log_write_uint64(DltContextData *log, uint64_t data)
1541 if ((log->size+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1546 if (dlt_user.verbose_mode)
1548 if ((log->size+sizeof(uint32_t)+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1553 type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
1555 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1556 log->size +=sizeof(uint32_t);
1559 memcpy((log->buffer)+log->size,&data,sizeof(uint64_t));
1560 log->size += sizeof(uint64_t);
1567 int dlt_user_log_write_int(DltContextData *log, int data)
1574 switch (sizeof(int))
1578 return dlt_user_log_write_int8(log, (int8_t)data);
1583 return dlt_user_log_write_int16(log, (int16_t)data);
1588 return dlt_user_log_write_int32(log, (int32_t)data);
1593 return dlt_user_log_write_int64(log, (int64_t)data);
1606 int dlt_user_log_write_int8(DltContextData *log, int8_t data)
1615 if ((log->size+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1620 if (dlt_user.verbose_mode)
1622 if ((log->size+sizeof(uint32_t)+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1627 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
1629 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1630 log->size += sizeof(uint32_t);
1633 memcpy((log->buffer)+log->size,&data,sizeof(int8_t));
1634 log->size += sizeof(int8_t);
1641 int dlt_user_log_write_int16(DltContextData *log, int16_t data)
1650 if ((log->size+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1655 if (dlt_user.verbose_mode)
1657 if ((log->size+sizeof(uint32_t)+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1662 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
1664 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1665 log->size += sizeof(uint32_t);
1668 memcpy((log->buffer)+log->size,&data,sizeof(int16_t));
1669 log->size += sizeof(int16_t);
1676 int dlt_user_log_write_int32(DltContextData *log, int32_t data)
1685 if ((log->size+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1690 if (dlt_user.verbose_mode)
1692 if ((log->size+sizeof(uint32_t)+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1697 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
1699 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1700 log->size += sizeof(uint32_t);
1703 memcpy((log->buffer)+log->size,&data, sizeof(int32_t));
1704 log->size += sizeof(int32_t);
1711 int dlt_user_log_write_int64(DltContextData *log, int64_t data)
1720 if ((log->size+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1725 if (dlt_user.verbose_mode)
1727 if ((log->size+sizeof(uint32_t)+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1732 type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
1734 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1735 log->size += sizeof(uint32_t);
1738 memcpy((log->buffer)+log->size,&data,sizeof(int64_t));
1739 log->size += sizeof(int64_t);
1746 int dlt_user_log_write_bool(DltContextData *log, uint8_t data)
1755 if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1760 if (dlt_user.verbose_mode)
1762 if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1767 type_info = DLT_TYPE_INFO_BOOL;
1769 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1770 log->size += sizeof(uint32_t);
1773 memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1774 log->size += sizeof(uint8_t);
1781 int dlt_user_log_write_string(DltContextData *log, const char *text)
1786 if ((log==0) || (text==0))
1791 if ((log->size+(strlen(text)+1)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1796 if (dlt_user.verbose_mode)
1798 if ((log->size+(strlen(text)+1)+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1803 type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII;
1805 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1806 log->size += sizeof(uint32_t);
1809 arg_size = strlen(text) + 1;
1811 memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1812 log->size += sizeof(uint16_t);
1814 memcpy((log->buffer)+log->size,text,arg_size);
1815 log->size += arg_size;
1822 int dlt_user_log_write_utf8_string(DltContextData *log, const char *text)
1827 if ((log==0) || (text==0))
1832 arg_size = strlen(text)+1;
1834 if ((log->size+arg_size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1839 if (dlt_user.verbose_mode)
1841 if ((log->size+arg_size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1846 type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8;
1848 memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1849 log->size += sizeof(uint32_t);
1852 arg_size = strlen(text) + 1;
1854 memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1855 log->size += sizeof(uint16_t);
1857 memcpy((log->buffer)+log->size,text,arg_size);
1858 log->size += arg_size;
1865 int dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
1866 int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length))
1872 DltUserInjectionCallback *old;
1879 if (dlt_user_log_init(handle, &log)==-1)
1884 if (service_id<DLT_USER_INJECTION_MIN)
1888 /* This function doesn't make sense storing to local file is choosen;
1889 so terminate this function */
1890 if (dlt_user.dlt_is_file)
1897 if (dlt_user.dlt_ll_ts==0)
1903 /* Insert callback in corresponding table */
1904 i=handle->log_level_pos;
1906 /* Insert each service_id only once */
1907 for (k=0;k<dlt_user.dlt_ll_ts[i].nrcallbacks;k++)
1909 if ((dlt_user.dlt_ll_ts[i].injection_table) &&
1910 (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id))
1923 j=dlt_user.dlt_ll_ts[i].nrcallbacks;
1925 /* Allocate or expand injection table */
1926 if (dlt_user.dlt_ll_ts[i].injection_table == 0)
1928 dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback));
1929 if(dlt_user.dlt_ll_ts[i].injection_table == 0)
1937 old = dlt_user.dlt_ll_ts[i].injection_table;
1938 dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback)*(j+1));
1939 if(dlt_user.dlt_ll_ts[i].injection_table == 0)
1941 dlt_user.dlt_ll_ts[i].injection_table = old;
1945 memcpy(dlt_user.dlt_ll_ts[i].injection_table,old,sizeof(DltUserInjectionCallback)*j);
1949 dlt_user.dlt_ll_ts[i].nrcallbacks++;
1952 /* Store service_id and corresponding function pointer for callback function */
1953 dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id;
1954 dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = dlt_injection_callback;
1967 int total_size, used_size;
1968 dlt_user_check_buffer(&total_size, &used_size);
1970 if((total_size - used_size) < (total_size/2))
1978 * Send the start of a segment chain.
1979 * Returns -1 on failure
1981 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)
1992 if (dlt_user_log_init(handle, &log)==-1)
1998 if (dlt_user.dlt_ll_ts==0)
2003 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2007 log.trace_status = nw_trace_type;
2010 gettimeofday(&tv, NULL);
2013 /* Write identifier */
2014 if(dlt_user_log_write_string(&log, "NWST") < 0)
2019 /* Write stream handle */
2020 if(dlt_user_log_write_uint16(&log, *id) < 0)
2026 if(dlt_user_log_write_raw(&log, header, header_len) < 0)
2031 /* Write size of payload */
2032 if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2037 /* Write expected segment count */
2038 uint16_t segment_count = payload_len/DLT_MAX_TRACE_SEGMENT_SIZE+1;
2040 /* If segments align perfectly with segment size, avoid sending empty segment */
2041 if((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0)
2046 if(dlt_user_log_write_uint16(&log, segment_count) < 0)
2051 /* Write length of one segment */
2052 if(dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0)
2058 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2063 int dlt_user_trace_network_segmented_segment(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
2065 while(check_buffer() < 0)
2067 usleep(1000*50); // Wait 50ms
2068 dlt_user_log_resend_buffer();
2078 if (dlt_user_log_init(handle, &log)==-1)
2083 if (dlt_user.dlt_ll_ts==0)
2088 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2092 log.trace_status = nw_trace_type;
2095 /* Write identifier */
2096 if(dlt_user_log_write_string(&log, "NWCH") < 0)
2101 /* Write stream handle */
2102 if(dlt_user_log_write_uint16(&log, id) < 0)
2107 /* Write segment sequence number */
2108 if(dlt_user_log_write_uint16(&log, sequence) < 0)
2114 if(dlt_user_log_write_raw(&log, payload, payload_len) < 0)
2120 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2123 /* Allow other threads to log between chunks */
2128 int dlt_user_trace_network_segmented_end(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type)
2137 if (dlt_user_log_init(handle, &log)==-1)
2144 if (dlt_user.dlt_ll_ts==0)
2149 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2153 log.trace_status = nw_trace_type;
2156 /* Write identifier */
2157 if(dlt_user_log_write_string(&log, "NWEN") < 0)
2162 /* Write stream handle */
2163 if(dlt_user_log_write_uint(&log, id) < 0)
2169 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2175 void dlt_user_trace_network_segmented_thread(void *unused)
2177 /* Unused on purpose. */
2180 prctl(PR_SET_NAME, "dlt_segmented", 0, 0, 0);
2183 s_segmented_data *data;
2187 // Wait until message queue is initialized
2188 pthread_mutex_lock(&mq_mutex);
2189 if(dlt_user.dlt_segmented_queue_read_handle < 0)
2191 pthread_cond_wait(&mq_init_condition, &mq_mutex);
2193 pthread_mutex_unlock(&mq_mutex);
2195 ssize_t read = mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char *)&data,
2196 sizeof(s_segmented_data * ), NULL);
2198 if(read != sizeof(s_segmented_data *))
2202 snprintf(str,254,"NWTSegmented: Error while reading queue: %s \n",strerror(errno));
2203 dlt_log(LOG_CRIT, str);
2207 /* Indicator just to try to flush the buffer */
2208 if(data->payload_len == DLT_DELAYED_RESEND_INDICATOR_PATTERN)
2210 // Sleep 100ms, to allow other process to read FIFO
2212 if(dlt_user_log_resend_buffer() < 0)
2214 // Requeue if still not empty
2215 if ( dlt_user_queue_resend() < 0 )
2217 //dlt_log(LOG_WARNING, "Failed to queue resending in dlt_user_trace_network_segmented_thread.\n");
2224 dlt_user_trace_network_segmented_thread_segmenter(data);
2226 /* Send the end message */
2227 DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type);
2228 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2230 dlt_log(LOG_ERR,"NWTSegmented: Could not send end segment.\n");
2233 /* Free resources */
2235 free(data->payload);
2240 void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data)
2242 /* Segment the data and send the chunks */
2244 uint16_t offset = 0;
2245 uint16_t sequence = 0;
2249 if(offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len)
2251 len = data->payload_len - offset;
2255 len = DLT_MAX_TRACE_SEGMENT_SIZE;
2257 /* If payload size aligns perfectly with segment size, avoid sending empty segment */
2263 ptr = data->payload + offset;
2264 DltReturnValue err = dlt_user_trace_network_segmented_segment(data->id, data->handle, data->nw_trace_type, sequence++, len, ptr);
2265 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2267 dlt_log(LOG_ERR,"NWTSegmented: Could not send segment. Aborting.\n");
2271 }while(ptr < data->payload + data->payload_len);
2275 int dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2277 /* Send as normal trace if possible */
2278 if(header_len+payload_len+sizeof(uint16_t) < DLT_USER_BUF_MAX_SIZE) {
2279 return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload);
2282 /* Allocate Memory */
2283 s_segmented_data *thread_data = malloc(sizeof(s_segmented_data));
2284 if(thread_data == NULL)
2288 thread_data->header = malloc(header_len);
2289 if(thread_data->header == NULL)
2294 thread_data->payload = malloc(payload_len);
2295 if(thread_data->payload == NULL)
2297 free(thread_data->header);
2303 thread_data->handle = handle;
2304 thread_data->nw_trace_type = nw_trace_type;
2305 thread_data->header_len = header_len;
2306 memcpy(thread_data->header, header, header_len);
2307 thread_data->payload_len = payload_len;
2308 memcpy(thread_data->payload, payload, payload_len);
2310 /* Send start message */
2311 DltReturnValue err = dlt_user_trace_network_segmented_start(&(thread_data->id),
2312 thread_data->handle, thread_data->nw_trace_type,
2313 thread_data->header_len, thread_data->header,
2314 thread_data->payload_len);
2315 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2317 dlt_log(LOG_ERR,"NWTSegmented: Could not send start segment. Aborting.\n");
2318 free(thread_data->header);
2319 free(thread_data->payload);
2324 /* Open queue if it is not open */
2325 if(dlt_init_message_queue() < 0)
2327 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2328 free(thread_data->header);
2329 free(thread_data->payload);
2336 if(mq_send(dlt_user.dlt_segmented_queue_write_handle,
2337 (char *)&thread_data, sizeof(s_segmented_data *), 1) < 0)
2341 dlt_log(LOG_ERR, "NWTSegmented: Queue full. Message discarded.\n");
2343 free(thread_data->header);
2344 free(thread_data->payload);
2347 snprintf(str,255,"NWTSegmented: Could not write into queue: %s \n",strerror(errno));
2348 dlt_log(LOG_CRIT, str);
2352 //thread_data will be freed by the receiver function
2353 //coverity[leaked_storage]
2357 int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2359 return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1);
2362 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)
2366 if (dlt_user_initialised==0)
2374 if (dlt_user_log_init(handle, &log)==-1)
2384 /* Commented out because of DltNetworkTraceType:
2386 if ((nw_trace_type<=0) || (nw_trace_type>0x15))
2393 if (dlt_user.dlt_ll_ts==0)
2398 if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2402 log.trace_status = nw_trace_type;
2410 /* If truncation is allowed, check if we must do it */
2411 if(allow_truncate > 0 && (header_len+payload_len+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
2413 /* Identify as truncated */
2414 if(dlt_user_log_write_string(&log, "NWTR") < 0)
2419 /* Write header and its length */
2420 if (dlt_user_log_write_raw(&log, header, header_len) < 0)
2425 /* Write original size of payload */
2426 if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2432 * Calculate maximum avaialble space in sending buffer after headers.
2435 int truncated_payload_len = DLT_USER_BUF_MAX_SIZE -
2436 log.size - sizeof(uint16_t) - sizeof(uint32_t);
2438 /* Write truncated payload */
2439 if (dlt_user_log_write_raw(&log, payload, truncated_payload_len) < 0)
2444 else /* Truncation not allowed or data short enough */
2446 /* Write header and its length */
2447 if (dlt_user_log_write_raw(&log, header, header_len)==-1)
2457 /* Write payload and its length */
2458 if (dlt_user_log_write_raw(&log, payload, payload_len)==-1)
2465 return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2471 int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
2475 if (dlt_user.verbose_mode==0)
2480 if ((handle==0) || (text==0))
2485 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2487 if (dlt_user_log_write_string(&log,text)==-1)
2491 if (dlt_user_log_write_finish(&log)==-1)
2500 int dlt_log_string_int(DltContext *handle,DltLogLevelType loglevel, const char *text, int data)
2504 if (dlt_user.verbose_mode==0)
2509 if ((handle==0) || (text==0))
2514 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2516 if (dlt_user_log_write_string(&log,text)==-1)
2520 if (dlt_user_log_write_int(&log,data)==-1)
2524 if (dlt_user_log_write_finish(&log)==-1)
2533 int dlt_log_string_uint(DltContext *handle,DltLogLevelType loglevel, const char *text, unsigned int data)
2537 if (dlt_user.verbose_mode==0)
2542 if ((handle==0) || (text==0))
2547 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2549 if (dlt_user_log_write_string(&log,text)==-1)
2553 if (dlt_user_log_write_uint(&log,data)==-1)
2557 if (dlt_user_log_write_finish(&log)==-1)
2566 int dlt_log_int(DltContext *handle,DltLogLevelType loglevel, int data)
2570 if (dlt_user.verbose_mode==0)
2580 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2582 if (dlt_user_log_write_int(&log,data)==-1)
2586 if (dlt_user_log_write_finish(&log)==-1)
2595 int dlt_log_uint(DltContext *handle,DltLogLevelType loglevel, unsigned int data)
2599 if (dlt_user.verbose_mode==0)
2609 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2611 if (dlt_user_log_write_uint(&log,data)==-1)
2615 if (dlt_user_log_write_finish(&log)==-1)
2624 int dlt_log_raw(DltContext *handle,DltLogLevelType loglevel, void *data,uint16_t length)
2628 if (dlt_user.verbose_mode==0)
2638 if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2640 if (dlt_user_log_write_raw(&log,data,length)==-1)
2644 if (dlt_user_log_write_finish(&log)==-1)
2653 int dlt_verbose_mode(void)
2655 if (dlt_user_initialised==0)
2663 /* Switch to verbose mode */
2664 dlt_user.verbose_mode = 1;
2669 int dlt_nonverbose_mode(void)
2671 if (dlt_user_initialised==0)
2679 /* Switch to non-verbose mode */
2680 dlt_user.verbose_mode = 0;
2685 int dlt_enable_local_print(void)
2687 if (dlt_user_initialised==0)
2695 dlt_user.enable_local_print = 1;
2700 int dlt_disable_local_print(void)
2702 if (dlt_user_initialised==0)
2710 dlt_user.enable_local_print = 0;
2715 void dlt_user_receiverthread_function(__attribute__((unused)) void *ptr)
2718 prctl(PR_SET_NAME, "dlt_receiver", 0, 0, 0);
2722 /* Check for new messages from DLT daemon */
2723 if (dlt_user_log_check_user_message()==-1)
2725 /* Critical error */
2726 dlt_log(LOG_CRIT,"Receiver thread encountered error condition\n");
2729 usleep(DLT_USER_RECEIVE_DELAY); /* delay */
2733 /* Private functions of user library */
2735 int dlt_user_log_init(DltContext *handle, DltContextData *log)
2737 if (dlt_user_initialised==0)
2745 log->handle = handle;
2750 int dlt_user_queue_resend(void)
2752 static unsigned char dlt_user_queue_resend_error_counter = 0;
2754 if(dlt_user.dlt_log_handle < 0)
2756 // Fail silenty. FIFO is not open yet
2760 * Ask segmented thread to try emptying the buffer soon.
2761 * This will be freed in dlt_user_trace_network_segmented_thread
2763 s_segmented_data *resend_data = malloc(sizeof(s_segmented_data));
2765 if (NULL == resend_data)
2770 resend_data->payload_len = DLT_DELAYED_RESEND_INDICATOR_PATTERN;
2774 /* Open queue if it is not open */
2775 if(dlt_init_message_queue() < 0)
2777 if(!dlt_user_queue_resend_error_counter)
2779 // log error only when problem occurred first time
2780 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2782 dlt_user_queue_resend_error_counter = 1;
2787 if(mq_send(dlt_user.dlt_segmented_queue_write_handle, (char *)&resend_data, sizeof(s_segmented_data *), 1) < 0)
2789 if(!dlt_user_queue_resend_error_counter)
2791 // log error only when problem occurred first time
2793 snprintf(str,254,"Could not request resending.: %s \n",strerror(errno));
2794 dlt_log(LOG_CRIT, str);
2796 dlt_user_queue_resend_error_counter = 1;
2801 dlt_user_queue_resend_error_counter = 0;
2803 //thread_data will be freed by the receiver function
2804 //coverity[leaked_storage]
2808 DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype)
2811 DltUserHeader userheader;
2814 DltReturnValue ret = DLT_RETURN_OK;
2818 return DLT_RETURN_ERROR;
2823 return DLT_RETURN_ERROR;
2826 if (dlt_user.appID[0]=='\0')
2828 return DLT_RETURN_ERROR;
2831 if (log->handle->contextID[0]=='\0')
2833 return DLT_RETURN_ERROR;
2836 if ((mtype<DLT_TYPE_LOG) || (mtype>DLT_TYPE_CONTROL))
2838 return DLT_RETURN_ERROR;
2841 /* also for Trace messages */
2842 #ifdef DLT_SHM_ENABLE
2843 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_SHM)==-1)
2845 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
2848 return DLT_RETURN_ERROR;
2851 if (dlt_message_init(&msg,0)==-1)
2853 return DLT_RETURN_ERROR;
2856 msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
2858 if (dlt_set_storageheader(msg.storageheader,dlt_user.ecuID)==-1)
2860 return DLT_RETURN_ERROR;
2863 msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
2864 msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_PROTOCOL_VERSION1 ;
2866 if (dlt_user.verbose_mode)
2868 /* In verbose mode, send extended header */
2869 msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2873 /* In non-verbose, send extended header if desired */
2874 #if (DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE==1)
2875 msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2879 #if (BYTE_ORDER==BIG_ENDIAN)
2880 msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
2883 msg.standardheader->mcnt = log->handle->mcnt++;
2885 /* Set header extra parameters */
2886 dlt_set_id(msg.headerextra.ecu,dlt_user.ecuID);
2887 //msg.headerextra.seid = 0;
2888 msg.headerextra.tmsp = dlt_uptime();
2890 if (dlt_message_set_extraparameters(&msg,0)==-1)
2892 return DLT_RETURN_ERROR;
2895 /* Fill out extended header, if extended header should be provided */
2896 if (DLT_IS_HTYP_UEH(msg.standardheader->htyp))
2898 /* with extended header */
2899 msg.extendedheader = (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp) );
2905 msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2908 case DLT_TYPE_NW_TRACE:
2910 msg.extendedheader->msin = (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT) | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2915 /* This case should not occur */
2916 return DLT_RETURN_ERROR;
2921 /* If in verbose mode, set flag in header for verbose mode */
2922 if (dlt_user.verbose_mode)
2924 msg.extendedheader->msin |= DLT_MSIN_VERB;
2927 msg.extendedheader->noar = log->args_num; /* number of arguments */
2928 dlt_set_id(msg.extendedheader->apid,dlt_user.appID); /* application id */
2929 dlt_set_id(msg.extendedheader->ctid,log->handle->contextID); /* context id */
2931 msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2935 /* without extended header */
2936 msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2939 len=msg.headersize - sizeof(DltStorageHeader) +log->size;
2942 dlt_log(LOG_CRIT,"Huge message discarded!\n");
2943 return DLT_RETURN_ERROR;
2946 msg.standardheader->len = DLT_HTOBE_16(len);
2948 /* print to std out, if enabled */
2949 if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) &&
2950 (dlt_user.local_print_mode != DLT_PM_AUTOMATIC))
2952 if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
2954 if (dlt_user_print_msg(&msg, log)==-1)
2956 return DLT_RETURN_ERROR;
2961 if (dlt_user.dlt_is_file)
2964 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size);
2969 /* Reattach to daemon if neccesary */
2970 dlt_user_log_reattach_to_daemon();
2972 if (dlt_user.overflow_counter)
2974 if (dlt_user_log_send_overflow()==0)
2976 sprintf(str,"%u messages discarded!\n",dlt_user.overflow_counter);
2977 dlt_log(LOG_ERR, str);
2978 dlt_user.overflow_counter=0;
2982 /* try to resent old data first */
2983 ret = DLT_RETURN_OK;
2984 if(dlt_user.dlt_log_handle!=-1)
2985 ret = dlt_user_log_resend_buffer();
2986 if(ret==DLT_RETURN_OK)
2988 /* resend ok or nothing to resent */
2989 #ifdef DLT_SHM_ENABLE
2990 if(dlt_user.dlt_log_handle!=-1)
2991 dlt_shm_push(&dlt_user.dlt_shm,msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
2992 log->buffer, log->size,0,0);
2995 ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
2996 &(userheader), sizeof(DltUserHeader),
3001 #ifdef DLT_TEST_ENABLE
3002 if(dlt_user.corrupt_user_header) {
3003 userheader.pattern[0]=0xff;
3004 userheader.pattern[1]=0xff;
3005 userheader.pattern[2]=0xff;
3006 userheader.pattern[3]=0xff;
3008 if(dlt_user.corrupt_message_size) {
3009 msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
3012 ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
3013 &(userheader), sizeof(DltUserHeader),
3014 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3015 log->buffer, log->size);
3019 /* store message in ringbuffer, if an error has occured */
3020 if (ret!=DLT_RETURN_OK)
3024 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3025 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3026 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3027 log->buffer, log->size)==-1)
3029 if(dlt_user.overflow_counter==0)
3032 dlt_log(LOG_ERR,"Buffer full! Messages will be discarded.\n");
3034 ret = DLT_RETURN_BUFFER_FULL;
3039 // Fail silenty if FIFO is not open
3040 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3042 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_log: Failed to queue resending.\n");
3048 case DLT_RETURN_BUFFER_FULL:
3051 dlt_user.overflow_counter += 1;
3052 return DLT_RETURN_BUFFER_FULL;
3054 case DLT_RETURN_PIPE_FULL:
3056 /* data could not be written */
3057 return DLT_RETURN_PIPE_FULL;
3059 case DLT_RETURN_PIPE_ERROR:
3061 /* handle not open or pipe error */
3062 close(dlt_user.dlt_log_handle);
3063 dlt_user.dlt_log_handle = -1;
3065 #ifdef DLT_SHM_ENABLE
3066 /* free shared memory */
3067 dlt_shm_free_client(&dlt_user.dlt_shm);
3070 if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
3072 dlt_user_print_msg(&msg, log);
3075 return DLT_RETURN_PIPE_ERROR;
3077 case DLT_RETURN_ERROR:
3079 /* other error condition */
3080 return DLT_RETURN_ERROR;
3084 return DLT_RETURN_OK;
3088 /* This case should never occur. */
3089 return DLT_RETURN_ERROR;
3094 return DLT_RETURN_OK;
3097 int dlt_user_log_send_register_application(void)
3099 DltUserHeader userheader;
3100 DltUserControlMsgRegisterApplication usercontext;
3104 if (dlt_user.appID[0]=='\0')
3109 /* set userheader */
3110 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION)==-1)
3115 /* set usercontext */
3116 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3117 usercontext.pid = getpid();
3119 if (dlt_user.application_description!=0)
3121 usercontext.description_length = strlen(dlt_user.application_description);
3125 usercontext.description_length = 0;
3128 if (dlt_user.dlt_is_file)
3134 ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication),dlt_user.application_description,usercontext.description_length);
3136 /* store message in ringbuffer, if an error has occured */
3137 if (ret!=DLT_RETURN_OK)
3141 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3142 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3143 (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterApplication),
3144 (const unsigned char*)dlt_user.application_description, usercontext.description_length)==-1)
3146 dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3153 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3155 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_application: Failed to queue resending.\n");
3162 int dlt_user_log_send_unregister_application(void)
3164 DltUserHeader userheader;
3165 DltUserControlMsgUnregisterApplication usercontext;
3169 if (dlt_user.appID[0]=='\0')
3174 /* set userheader */
3175 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION)==-1)
3180 /* set usercontext */
3181 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3182 usercontext.pid = getpid();
3184 if (dlt_user.dlt_is_file)
3190 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication));
3191 return ((ret==DLT_RETURN_OK)?0:-1);
3194 int dlt_user_log_send_register_context(DltContextData *log)
3196 DltUserHeader userheader;
3197 DltUserControlMsgRegisterContext usercontext;
3210 if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3215 /* set userheader */
3216 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT)==-1)
3221 /* set usercontext */
3222 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3223 dlt_set_id(usercontext.ctid,log->handle->contextID); /* context id */
3224 usercontext.log_level_pos = log->handle->log_level_pos;
3225 usercontext.pid = getpid();
3227 usercontext.log_level = (int8_t)log->log_level;
3228 usercontext.trace_status = (int8_t)log->trace_status;
3230 if (log->context_description!=0)
3232 usercontext.description_length = strlen(log->context_description);
3236 usercontext.description_length = 0;
3239 if (dlt_user.dlt_is_file)
3245 ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext),log->context_description,usercontext.description_length);
3247 /* store message in ringbuffer, if an error has occured */
3248 if (ret!=DLT_RETURN_OK)
3252 if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3253 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3254 (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterContext),
3255 (const unsigned char*)log->context_description, usercontext.description_length)==-1)
3257 dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3264 if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3266 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_context: Failed to queue resending.\n");
3274 int dlt_user_log_send_unregister_context(DltContextData *log)
3276 DltUserHeader userheader;
3277 DltUserControlMsgUnregisterContext usercontext;
3290 if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3295 /* set userheader */
3296 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT)==-1)
3301 /* set usercontext */
3302 dlt_set_id(usercontext.apid,dlt_user.appID); /* application id */
3303 dlt_set_id(usercontext.ctid,log->handle->contextID); /* context id */
3304 usercontext.pid = getpid();
3306 if (dlt_user.dlt_is_file)
3312 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext));
3313 return ((ret==DLT_RETURN_OK)?0:-1);
3316 int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
3318 DltUserHeader userheader;
3319 DltUserControlMsgAppLogLevelTraceStatus usercontext;
3322 if ((appid==0) || (appid[0]=='\0'))
3327 /* Removed because of DltLogLevelType and DltTraceStatusType
3329 if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
3334 if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
3341 /* set userheader */
3342 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS)==-1)
3347 /* set usercontext */
3348 dlt_set_id(usercontext.apid,appid); /* application id */
3349 usercontext.log_level = loglevel;
3350 usercontext.trace_status = tracestatus;
3352 if (dlt_user.dlt_is_file)
3358 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus));
3359 return ((ret==DLT_RETURN_OK)?0:-1);
3362 int dlt_user_log_send_log_mode(DltUserLogMode mode)
3364 DltUserHeader userheader;
3365 DltUserControlMsgLogMode logmode;
3369 /* set userheader */
3370 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE)==-1)
3376 logmode.log_mode = (unsigned char) mode;
3378 if (dlt_user.dlt_is_file)
3384 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode));
3385 return ((ret==DLT_RETURN_OK)?0:-1);
3388 int dlt_user_print_msg(DltMessage *msg, DltContextData *log)
3390 uint8_t *databuffer_tmp;
3391 int32_t datasize_tmp;
3392 int32_t databuffersize_tmp;
3393 static char text[DLT_USER_TEXT_LENGTH];
3395 if ((msg==0) || (log==0))
3400 /* Save variables before print */
3401 databuffer_tmp = msg->databuffer;
3402 datasize_tmp = msg->datasize;
3403 databuffersize_tmp = msg->databuffersize;
3405 /* Act like a receiver, convert header back to host format */
3406 msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len);
3407 dlt_message_get_extraparameters(msg,0);
3409 msg->databuffer = log->buffer;
3410 msg->datasize = log->size;
3411 msg->databuffersize = log->size;
3413 /* Print message as ASCII */
3414 if (dlt_message_print_ascii(msg,text,DLT_USER_TEXT_LENGTH,0)==-1)
3419 /* Restore variables and set len to BE*/
3420 msg->databuffer = databuffer_tmp;
3421 msg->databuffersize = databuffersize_tmp;
3422 msg->datasize = datasize_tmp;
3424 msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
3429 int dlt_user_log_check_user_message(void)
3436 DltUserHeader *userheader;
3437 DltReceiver *receiver = &(dlt_user.receiver);
3439 DltUserControlMsgLogLevel *usercontextll;
3440 DltUserControlMsgInjection *usercontextinj;
3441 DltUserControlMsgLogState *userlogstate;
3442 unsigned char *userbuffer;
3444 /* For delayed calling of injection callback, to avoid deadlock */
3445 DltUserInjectionCallback delayed_injection_callback;
3446 unsigned char *delayed_inject_buffer = 0;
3447 uint32_t delayed_inject_data_length = 0;
3449 /* Ensure that callback is null before searching for it */
3450 delayed_injection_callback.injection_callback = 0;
3451 delayed_injection_callback.service_id = 0;
3453 if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
3457 if (dlt_receiver_receive_fd(receiver)<=0)
3459 /* No new message available */
3463 /* look through buffer as long as data is in there */
3466 if (receiver->bytesRcvd < (int32_t)sizeof(DltUserHeader))
3471 /* resync if necessary */
3475 userheader = (DltUserHeader*) (receiver->buf+offset);
3477 /* Check for user header pattern */
3478 if (dlt_user_check_userheader(userheader))
3485 while ((int32_t)(sizeof(DltUserHeader)+offset)<=receiver->bytesRcvd);
3487 /* Check for user header pattern */
3488 if (dlt_user_check_userheader(userheader)<0 ||
3489 dlt_user_check_userheader(userheader)==0)
3494 /* Set new start offset */
3497 receiver->buf+=offset;
3498 receiver->bytesRcvd-=offset;
3501 switch (userheader->message)
3503 case DLT_USER_MESSAGE_LOG_LEVEL:
3505 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel)))
3511 usercontextll = (DltUserControlMsgLogLevel*) (receiver->buf+sizeof(DltUserHeader));
3513 /* Update log level and trace status */
3514 if (usercontextll!=0)
3518 if ((usercontextll->log_level_pos >= 0) && (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries))
3520 // printf("Store ll, ts\n");
3521 if (dlt_user.dlt_ll_ts)
3523 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = usercontextll->log_level;
3524 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status = usercontextll->trace_status;
3525 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr)
3526 *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) = usercontextll->log_level;
3527 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr)
3528 *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) = usercontextll->trace_status;
3535 /* keep not read data in buffer */
3536 if (dlt_receiver_remove(receiver,sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel))==-1)
3542 case DLT_USER_MESSAGE_INJECTION:
3544 /* At least, user header, user context, and service id and data_length of injected message is available */
3545 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)))
3551 usercontextinj = (DltUserControlMsgInjection*) (receiver->buf+sizeof(DltUserHeader));
3552 userbuffer = (unsigned char*) (receiver->buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection));
3557 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))
3565 if ((usercontextinj->data_length_inject>0) && (dlt_user.dlt_ll_ts))
3567 /* Check if injection callback is registered for this context */
3568 for (i=0; i<dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks;i++)
3570 if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) &&
3571 (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id == usercontextinj->service_id))
3573 /* Prepare delayed injection callback call */
3574 if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback!=0)
3576 delayed_injection_callback.injection_callback = dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback;
3577 delayed_injection_callback.service_id = usercontextinj->service_id;
3578 delayed_inject_data_length = usercontextinj->data_length_inject;
3579 delayed_inject_buffer = malloc(delayed_inject_data_length);
3580 if(delayed_inject_buffer != 0) {
3581 memcpy(delayed_inject_buffer, userbuffer, delayed_inject_data_length);
3592 /* Delayed injection callback call */
3593 if(delayed_inject_buffer != 0 && delayed_injection_callback.injection_callback != 0) {
3594 delayed_injection_callback.injection_callback(delayed_injection_callback.service_id, delayed_inject_buffer, delayed_inject_data_length);
3595 delayed_injection_callback.injection_callback = 0;
3596 free(delayed_inject_buffer);
3597 delayed_inject_buffer = NULL;
3601 /* keep not read data in buffer */
3602 if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))==-1)
3609 case DLT_USER_MESSAGE_LOG_STATE:
3611 /* At least, user header, user context, and service id and data_length of injected message is available */
3612 if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))
3618 userlogstate = (DltUserControlMsgLogState*) (receiver->buf+sizeof(DltUserHeader));
3619 dlt_user.log_state = userlogstate->log_state;
3621 /* keep not read data in buffer */
3622 if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))==-1)
3630 dlt_log(LOG_ERR,"Invalid user message type received!\n");
3632 dlt_receiver_remove(receiver,sizeof(DltUserHeader));
3633 /* In next invocation of while loop, a resync will be triggered if additional data was received */
3646 if (dlt_receiver_move_to_begin(receiver)==-1)
3650 } /* while receive */
3653 return DLT_RETURN_OK;
3656 int dlt_user_log_resend_buffer(void)
3662 /* Send content of ringbuffer */
3664 count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
3667 for (num=0;num<count;num++)
3671 size = dlt_buffer_copy(&(dlt_user.startup_buffer),dlt_user.resend_buffer,sizeof(dlt_user.resend_buffer));
3675 #ifdef DLT_SHM_ENABLE
3676 dlt_shm_push(&dlt_user.dlt_shm,dlt_user.resend_buffer+sizeof(DltUserHeader),size-sizeof(DltUserHeader),0,0,0,0);
3679 ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,sizeof(DltUserHeader),0,0,0,0);
3682 ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,size,0,0,0,0);
3685 /* in case of error, keep message in ringbuffer */
3686 if (ret==DLT_RETURN_OK)
3688 dlt_buffer_remove(&(dlt_user.startup_buffer));
3692 /* keep message in ringbuffer */
3703 void dlt_user_log_reattach_to_daemon(void)
3705 uint32_t num,reregistered=0;
3708 DltContextData log_new;
3710 if (dlt_user.dlt_log_handle<0)
3712 dlt_user.dlt_log_handle=-1;
3714 /* try to open pipe to dlt daemon */
3715 dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK);
3716 if (dlt_user.dlt_log_handle > 0)
3718 if (dlt_user_log_init(&handle,&log_new)==-1)
3723 #ifdef DLT_SHM_ENABLE
3724 /* init shared memory */
3725 if (dlt_shm_init_client(&dlt_user.dlt_shm,DLT_SHM_KEY) < 0)
3727 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
3728 dlt_log(LOG_WARNING, str);
3733 dlt_log(LOG_NOTICE, "Logging re-enabled!\n");
3735 /* Re-register application */
3736 if (dlt_user_log_send_register_application()==-1)
3743 /* Re-register all stored contexts */
3744 for (num=0; num<dlt_user.dlt_ll_ts_num_entries; num++)
3746 /* Re-register stored context */
3747 if ((dlt_user.appID[0]!='\0') && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID[0]!='\0'))
3749 //dlt_set_id(log_new.appID, dlt_user.appID);
3750 dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
3751 handle.log_level_pos = num;
3752 log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
3754 // Release the mutex for sending context registration:
3755 // function dlt_user_log_send_register_context() can take the mutex to write to the DLT buffer. => dead lock
3758 log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
3759 log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
3761 if (dlt_user_log_send_register_context(&log_new)==-1)
3768 // Lock again the mutex
3769 // it is necessary in the for(;;) test, in order to have coherent dlt_user data all over the critical section.
3777 if (reregistered==1)
3779 dlt_user_log_resend_buffer();
3785 int dlt_user_log_send_overflow(void)
3787 DltUserHeader userheader;
3788 DltUserControlMsgBufferOverflow userpayload;
3791 /* set userheader */
3792 if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW)==-1)
3797 if (dlt_user.dlt_is_file)
3802 /* set user message parameters */
3803 userpayload.overflow_counter = dlt_user.overflow_counter;
3804 dlt_set_id(userpayload.apid,dlt_user.appID);
3807 ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader),
3808 &(userpayload), sizeof(DltUserControlMsgBufferOverflow));
3809 return ((ret==DLT_RETURN_OK)?0:-1);
3812 int dlt_user_check_buffer(int *total_size, int *used_size)
3814 #ifdef DLT_SHM_ENABLE
3815 *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm));
3816 *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm));
3818 *total_size = dlt_buffer_get_total_size(&(dlt_user.startup_buffer));
3819 *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer));
3825 #ifdef DLT_TEST_ENABLE
3826 void dlt_user_test_corrupt_user_header(int enable)
3828 dlt_user.corrupt_user_header = enable;
3830 void dlt_user_test_corrupt_message_size(int enable,int16_t size)
3832 dlt_user.corrupt_message_size = enable;
3833 dlt_user.corrupt_message_size_size = size;