c3eb29d24cd3324b36f61d812a94364481ebeac8
[profile/ivi/dlt-daemon.git] / src / lib / dlt_user.c
1 /**
2  * @licence app begin@
3  * Copyright (C) 2012  BMW AG
4  *
5  * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
6  *
7  * Contributions are licensed to the GENIVI Alliance under one or more
8  * Contribution License Agreements.
9  *
10  * \copyright
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/.
14  *
15  *
16  * \author Alexander Wenzel <alexander.aw.wenzel@bmw.de> BMW 2011-2012
17  *
18  * \file dlt_user.c
19  * For further information see http://www.genivi.org/.
20  * @licence end@
21  */
22
23
24 /*******************************************************************************
25 **                                                                            **
26 **  SRC-MODULE: dlt_user.c                                                    **
27 **                                                                            **
28 **  TARGET    : linux                                                         **
29 **                                                                            **
30 **  PROJECT   : DLT                                                           **
31 **                                                                            **
32 **  AUTHOR    : Alexander Wenzel Alexander.AW.Wenzel@bmw.de                   **
33 **              Markus Klein                                                  **
34 **                                                                            **
35 **  PURPOSE   :                                                               **
36 **                                                                            **
37 **  REMARKS   :                                                               **
38 **                                                                            **
39 **  PLATFORM DEPENDANT [yes/no]: yes                                          **
40 **                                                                            **
41 **  TO BE CHANGED BY USER [yes/no]: no                                        **
42 **                                                                            **
43 *******************************************************************************/
44
45 /*******************************************************************************
46 **                      Author Identity                                       **
47 ********************************************************************************
48 **                                                                            **
49 ** Initials     Name                       Company                            **
50 ** --------     -------------------------  ---------------------------------- **
51 **  aw          Alexander Wenzel           BMW                                **
52 **  mk          Markus Klein               Fraunhofer ESK                     **
53 *******************************************************************************/
54
55 /*******************************************************************************
56 **                      Revision Control History                              **
57 *******************************************************************************/
58
59 /*
60  * $LastChangedRevision: 1670 $
61  * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $
62  * $LastChangedBy$
63  Initials    Date         Comment
64  aw          13.01.2010   initial
65  */
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 */
69
70 #if !defined (__WIN32__)
71 #include <syslog.h> /* for LOG_... */
72 #include <semaphore.h>
73 #include <pthread.h>    /* POSIX Threads */
74 #endif
75
76 #include <sys/time.h>
77 #include <math.h>
78
79 #include <sys/stat.h>
80 #include <fcntl.h>
81 #include <errno.h>
82
83 #include <sys/uio.h> /* writev() */
84
85 #include <limits.h>
86 #include <sys/prctl.h>
87
88 #include "dlt_user.h"
89 #include "dlt_user_shared.h"
90 #include "dlt_user_shared_cfg.h"
91 #include "dlt_user_cfg.h"
92
93 static DltUser dlt_user;
94 static int dlt_user_initialised = 0;
95 static int dlt_user_freeing = 0;
96
97 static char str[DLT_USER_BUFFER_LENGTH];
98
99 static sem_t dlt_mutex;
100 static pthread_t dlt_receiverthread_handle;
101 static pthread_attr_t dlt_receiverthread_attr;
102
103 /* Segmented Network Trace */
104 #define DLT_MAX_TRACE_SEGMENT_SIZE 1024
105 #define DLT_MESSAGE_QUEUE_NAME "/dlt_message_queue"
106 #define DLT_DELAYED_RESEND_INDICATOR_PATTERN 0xFFFF
107
108 /* Mutex to wait on while message queue is not initialized */
109 pthread_mutex_t mq_mutex;
110 pthread_cond_t  mq_init_condition;
111
112 /* Structure to pass data to segmented thread */
113 typedef struct {
114         DltContext                      *handle;
115         uint16_t                        id;
116         DltNetworkTraceType     nw_trace_type;
117         uint16_t                        header_len;
118         void                            *header;
119         uint16_t                        payload_len;
120         void                            *payload;
121 } s_segmented_data;
122
123 /* Function prototypes for internally used functions */
124 static void dlt_user_receiverthread_function(void *ptr);
125 static void dlt_user_atexit_handler(void);
126 static int dlt_user_log_init(DltContext *handle, DltContextData *log);
127 static DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype);
128 static int dlt_user_log_send_register_application(void);
129 static int dlt_user_log_send_unregister_application(void);
130 static int dlt_user_log_send_register_context(DltContextData *log);
131 static int dlt_user_log_send_unregister_context(DltContextData *log);
132 static int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus);
133 static int dlt_user_log_send_log_mode(DltUserLogMode mode);
134 static int dlt_user_print_msg(DltMessage *msg, DltContextData *log);
135 static int dlt_user_log_check_user_message(void);
136 static void dlt_user_log_reattach_to_daemon(void);
137 static int dlt_user_log_send_overflow(void);
138 static void dlt_user_trace_network_segmented_thread(void *unused);
139 static void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data);
140 static int dlt_user_queue_resend(void);
141
142 int dlt_user_check_library_version(const char *user_major_version,const char *user_minor_version){
143
144         char str[200];
145         char lib_major_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
146         char lib_minor_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
147
148         dlt_get_major_version( lib_major_version);
149         dlt_get_minor_version( lib_minor_version);
150
151         if( (strcmp(lib_major_version,user_major_version)!=0) || (strcmp(lib_minor_version,user_minor_version)!=0))
152         {
153                 sprintf(str,"DLT Library version check failed! Installed DLT library version is %s.%s - Application using DLT library version %s.%s\n",lib_major_version,lib_minor_version,user_major_version,user_minor_version);
154                 dlt_log(LOG_WARNING, str);
155                 return -1;
156         }
157         return 0;
158 }
159
160 int dlt_init(void)
161 {
162     char filename[DLT_USER_MAX_FILENAME_LENGTH];
163     int ret;
164
165     // process is exiting. Do not allocate new resources.
166     if (dlt_user_freeing != 0)
167     {
168         // return negative value, to stop the current log
169         return -1;
170     }
171
172     // WARNING: multithread unsafe !
173     // Another thread will check that dlt_user_initialised != 0, but the lib is not initialised !
174     dlt_user_initialised = 1;
175
176     /* Initialize common part of dlt_init()/dlt_init_file() */
177     if (dlt_init_common()==-1)
178     {
179         dlt_user_initialised = 0;
180         return -1;
181     }
182
183     /* check environment variables */
184     dlt_check_envvar();
185
186     dlt_user.dlt_is_file = 0;
187     dlt_user.overflow = 0;
188     dlt_user.overflow_counter = 0;
189 #ifdef DLT_SHM_ENABLE
190         memset(&(dlt_user.dlt_shm),0,sizeof(DltShm));
191 #endif
192
193     /* create and open DLT user FIFO */
194     sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
195      
196     /* Try to delete existing pipe, ignore result of unlink */
197     unlink(filename);
198     
199     ret=mkfifo(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP );
200     if (ret==-1)
201     {
202         sprintf(str,"Loging disabled, FIFO user %s cannot be created!\n",filename);
203         dlt_log(LOG_WARNING, str);
204         /* return 0; */ /* removed to prevent error, when FIFO already exists */
205     }
206
207     // S_IWGRP cannot be set by mkfifo (???), let's reassign right bits
208     ret=chmod(filename, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP );
209     if (ret==-1)
210     {
211         sprintf(str,"FIFO user %s cannot be chmoded!\n", DLT_USER_DIR);
212         dlt_log(LOG_ERR, str);
213         return -1;
214     }
215
216     dlt_user.dlt_user_handle = open(filename, O_RDWR | O_CLOEXEC);
217     if (dlt_user.dlt_user_handle == DLT_FD_INIT)
218     {
219         sprintf(str,"Loging disabled, FIFO user %s cannot be opened!\n",filename);
220         dlt_log(LOG_WARNING, str);
221         unlink(filename);
222         return 0;
223     }
224
225     /* open DLT output FIFO */
226     dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK | O_CLOEXEC );
227     if (dlt_user.dlt_log_handle==-1)
228     {
229         sprintf(str,"Loging disabled, FIFO %s cannot be opened with open()!\n",DLT_USER_FIFO);
230         dlt_log(LOG_WARNING, str);
231         //return 0;
232     }
233         else
234         {
235 #ifdef DLT_SHM_ENABLE
236                 /* init shared memory */
237                 if (dlt_shm_init_client(&(dlt_user.dlt_shm),DLT_SHM_KEY) < 0)
238                 {
239                         sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
240                         dlt_log(LOG_WARNING, str);
241                         //return 0; 
242                 }   
243 #endif
244         }
245                 
246
247     if (dlt_receiver_init(&(dlt_user.receiver),dlt_user.dlt_user_handle, DLT_USER_RCVBUF_MAX_SIZE)==-1)
248         {
249         dlt_user_initialised = 0;
250         return -1;
251     }
252
253     /* Start receiver thread */
254     if (pthread_create(&(dlt_receiverthread_handle),
255                        0,
256                        (void *) &dlt_user_receiverthread_function,
257                        0)!=0)
258         {
259                 if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
260                 {
261                         dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
262                 }
263
264                 dlt_log(LOG_CRIT, "Can't create receiver thread!\n");
265                 dlt_user_initialised = 0;
266         return -1;
267         }
268
269     if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
270         {
271                 dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
272         }
273
274     /* These will be lazy initialized only when needed */
275     dlt_user.dlt_segmented_queue_read_handle = -1;
276     dlt_user.dlt_segmented_queue_write_handle = -1;
277
278     /* Wait mutext for segmented thread */
279     pthread_mutex_init(&mq_mutex, NULL);
280     pthread_cond_init(&mq_init_condition, NULL);
281
282     /* Start the segmented thread */
283         if(pthread_create(&(dlt_user.dlt_segmented_nwt_handle), NULL,
284            (void *)dlt_user_trace_network_segmented_thread, NULL))
285         {
286         dlt_log(LOG_CRIT, "Can't start segmented thread!\n");
287         return -1;
288         }
289
290         return 0;
291 }
292
293 int dlt_init_file(const char *name)
294 {
295     dlt_user_initialised = 1;
296
297     /* Initialize common part of dlt_init()/dlt_init_file() */
298     if (dlt_init_common()==-1)
299     {
300         dlt_user_initialised = 0;
301         return -1;
302     }
303
304     dlt_user.dlt_is_file = 1;
305
306     /* open DLT output file */
307     dlt_user.dlt_log_handle = open(name,O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
308     if (dlt_user.dlt_log_handle == -1)
309     {
310         sprintf(str,"Log file %s cannot be opened!\n",name);
311         dlt_log(LOG_ERR, str);
312         return -1;
313     }
314
315     return 0;
316 }
317
318 int dlt_init_message_queue(void)
319 {
320         pthread_mutex_lock(&mq_mutex);
321         if(dlt_user.dlt_segmented_queue_read_handle >= 0 &&
322            dlt_user.dlt_segmented_queue_write_handle >= 0)
323         {
324                 // Already intialized
325                 pthread_mutex_unlock(&mq_mutex);
326                 return 0;
327         }
328
329     /* Generate per process name for queue */
330     char queue_name[NAME_MAX];
331     sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
332
333     /* Maximum queue size is 10, limit to size of pointers */
334     struct mq_attr mqatr;
335     mqatr.mq_flags              = 0;
336     mqatr.mq_maxmsg             = 10;
337     mqatr.mq_msgsize    = sizeof(s_segmented_data *);
338     mqatr.mq_curmsgs    = 0;
339
340     /**
341      * Create the message queue. It must be newly created
342      * if old one was left by a crashing process.
343      * */
344     dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
345                 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
346     if(dlt_user.dlt_segmented_queue_read_handle < 0)
347     {
348         if(errno == EEXIST)
349         {
350                 dlt_log(LOG_WARNING, "Old message queue exists, trying to delete.\n");
351                 if(mq_unlink(queue_name) < 0)
352                 {
353                 char str[256];
354                 snprintf(str,255,"Could not delete existing message queue!: %s \n",strerror(errno));
355                 dlt_log(LOG_CRIT, str);
356                 }
357                 else // Retry
358                 {
359                         dlt_user.dlt_segmented_queue_read_handle = mq_open(queue_name, O_CREAT| O_RDONLY | O_EXCL,
360                                         S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, &mqatr);
361                 }
362         }
363         if(dlt_user.dlt_segmented_queue_read_handle < 0)
364         {
365             char str[256];
366             snprintf(str,255,"Can't create message queue read handle!: %s \n",strerror(errno));
367             dlt_log(LOG_CRIT, str);
368                 pthread_mutex_unlock(&mq_mutex);
369                 return -1;
370         }
371     }
372
373     dlt_user.dlt_segmented_queue_write_handle = mq_open(queue_name, O_WRONLY|O_NONBLOCK);
374     if(dlt_user.dlt_segmented_queue_write_handle < 0)
375     {
376
377         char str[256];
378         snprintf(str,255,"Can't open message queue write handle!: %s \n",strerror(errno));
379         dlt_log(LOG_CRIT, str);
380         pthread_mutex_unlock(&mq_mutex);
381         return -1;
382     }
383
384     pthread_cond_signal(&mq_init_condition);
385     pthread_mutex_unlock(&mq_mutex);
386     return 0;
387 }
388
389 int dlt_init_common(void)
390 {
391     char *env_local_print;
392
393     /* Binary semaphore for threads */
394     if (sem_init(&dlt_mutex, 0, 1)==-1)
395     {
396         dlt_user_initialised = 0;
397         return -1;
398     }
399
400         /* set to unknown state of connected client */
401         dlt_user.log_state = -1;
402
403     dlt_user.dlt_log_handle=-1;
404     dlt_user.dlt_user_handle=DLT_FD_INIT;
405
406     dlt_set_id(dlt_user.ecuID,DLT_USER_DEFAULT_ECU_ID);
407     dlt_set_id(dlt_user.appID,"");
408
409     dlt_user.application_description = 0;
410
411     /* Verbose mode is enabled by default */
412     dlt_user.verbose_mode = 1;
413
414     /* Local print is disabled by default */
415     dlt_user.enable_local_print = 0;
416
417     dlt_user.local_print_mode = DLT_PM_UNSET;
418
419     env_local_print = getenv(DLT_USER_ENV_LOCAL_PRINT_MODE);
420     if (env_local_print)
421     {
422         if (strcmp(env_local_print,"AUTOMATIC")==0)
423         {
424             dlt_user.local_print_mode = DLT_PM_AUTOMATIC;
425         }
426         else if (strcmp(env_local_print,"FORCE_ON")==0)
427         {
428             dlt_user.local_print_mode = DLT_PM_FORCE_ON;
429         }
430         else if (strcmp(env_local_print,"FORCE_OFF")==0)
431         {
432             dlt_user.local_print_mode = DLT_PM_FORCE_OFF;
433         }
434     }
435
436     /* Initialize LogLevel/TraceStatus field */
437     DLT_SEM_LOCK();
438     dlt_user.dlt_ll_ts = 0;
439     dlt_user.dlt_ll_ts_max_num_entries = 0;
440     dlt_user.dlt_ll_ts_num_entries = 0;
441
442     if (dlt_buffer_init_dynamic(&(dlt_user.startup_buffer), DLT_USER_RINGBUFFER_MIN_SIZE, DLT_USER_RINGBUFFER_MAX_SIZE, DLT_USER_RINGBUFFER_STEP_SIZE)==-1)
443     {
444                 dlt_user_initialised = 0;
445         DLT_SEM_FREE();
446         return -1;
447     }
448     DLT_SEM_FREE();
449
450     signal(SIGPIPE,SIG_IGN);                  /* ignore pipe signals */
451
452     atexit(dlt_user_atexit_handler);
453
454 #ifdef DLT_TEST_ENABLE
455     dlt_user.corrupt_user_header = 0;
456     dlt_user.corrupt_message_size = 0;
457     dlt_user.corrupt_message_size_size = 0;
458 #endif
459
460     return 0;
461 }
462
463 void dlt_user_atexit_handler(void)
464 {
465     if (dlt_user_initialised==0)
466     {
467         dlt_log(LOG_WARNING, "dlt_user_atexit_handler dlt_user_initialised==0\n");
468         // close file
469         dlt_log_free();
470         return;
471     }
472
473         /* Try to resend potential log messages in the user buffer */
474         int count = dlt_user_atexit_blow_out_user_buffer();
475
476         if(count != 0){
477                 char tmp[256];
478                 sprintf(tmp,"Lost log messages in user buffer when exiting: %i\n",count);
479                 dlt_log(LOG_ERR, tmp);
480         }
481
482     /* Unregister app (this also unregisters all contexts in daemon) */
483     /* Ignore return value */
484     dlt_unregister_app();
485
486     /* Cleanup */
487     /* Ignore return value */
488     dlt_free();
489 }
490
491 int dlt_user_atexit_blow_out_user_buffer(void){
492
493         int count,ret;
494
495         uint32_t exitTime = dlt_uptime() + DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT;
496
497         while(dlt_uptime() < exitTime ){
498
499                 ret = dlt_user_log_resend_buffer();
500
501                 if(ret == 0)
502                 {
503                                 return 0;
504                 }
505
506                 usleep(DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP);
507         }
508
509         DLT_SEM_LOCK();
510         count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
511         DLT_SEM_FREE();
512
513         return count;
514 }
515
516 int dlt_free(void)
517 {
518     uint32_t i;
519         char filename[DLT_USER_MAX_FILENAME_LENGTH];
520
521     if( dlt_user_freeing != 0 )
522         // resources are already being freed. Do nothing and return.
523         return -1;
524
525     // library is freeing its resources. Avoid to allocate it in dlt_init()
526     dlt_user_freeing = 1;
527
528     if (dlt_user_initialised==0)
529     {
530         dlt_user_freeing = 0;
531         return -1;
532     }
533     dlt_user_initialised = 0;
534
535     if (dlt_receiverthread_handle)
536     {
537         /* Ignore return value */
538         pthread_cancel(dlt_receiverthread_handle);
539     }
540
541     if (dlt_user.dlt_segmented_nwt_handle)
542     {
543         pthread_cancel(dlt_user.dlt_segmented_nwt_handle);
544     }
545
546     if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
547     {
548         sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
549
550         close(dlt_user.dlt_user_handle);
551         dlt_user.dlt_user_handle=DLT_FD_INIT;
552
553         unlink(filename);
554     }
555
556 #ifdef DLT_SHM_ENABLE
557         /* free shared memory */
558         dlt_shm_free_client(&dlt_user.dlt_shm);
559 #endif
560
561     if (dlt_user.dlt_log_handle!=-1)
562     {
563         /* close log file/output fifo to daemon */
564         close(dlt_user.dlt_log_handle);
565         dlt_user.dlt_log_handle = -1;
566     }
567
568         /* Ignore return value */
569     DLT_SEM_LOCK();
570     dlt_receiver_free(&(dlt_user.receiver));
571     DLT_SEM_FREE();
572
573         /* Ignore return value */
574     DLT_SEM_LOCK();
575     dlt_buffer_free_dynamic(&(dlt_user.startup_buffer));
576     DLT_SEM_FREE();
577
578     DLT_SEM_LOCK();
579     if (dlt_user.dlt_ll_ts)
580     {
581         for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
582         {
583             if (dlt_user.dlt_ll_ts[i].injection_table!=0)
584             {
585                 free(dlt_user.dlt_ll_ts[i].injection_table);
586                 dlt_user.dlt_ll_ts[i].injection_table = 0;
587             }
588             dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
589         }
590
591         free(dlt_user.dlt_ll_ts);
592         dlt_user.dlt_ll_ts = 0;
593         dlt_user.dlt_ll_ts_max_num_entries = 0;
594         dlt_user.dlt_ll_ts_num_entries = 0;
595     }
596     DLT_SEM_FREE();
597
598     char queue_name[NAME_MAX];
599     sprintf(queue_name, "%s.%d", DLT_MESSAGE_QUEUE_NAME, getpid());
600
601     /**
602      * Ignore errors from these, to not to spam user if dlt_free
603      * is accidentally called multiple times.
604      */
605     mq_close(dlt_user.dlt_segmented_queue_write_handle);
606     mq_close(dlt_user.dlt_segmented_queue_read_handle);
607     mq_unlink(queue_name);
608
609     // allow the user app to do dlt_init() again.
610     // The flag is unset only to keep almost the same behaviour as before, on EntryNav
611     // This should be removed for other projects (see documentation of dlt_free()
612     dlt_user_freeing = 0;
613
614     return 0;
615 }
616
617 int dlt_check_library_version(const char * user_major_version,const char * user_minor_version)
618 {
619         return dlt_user_check_library_version(user_major_version, user_minor_version);
620 }
621
622 int dlt_register_app(const char *appid, const char * description)
623 {
624     int ret;
625
626     if (dlt_user_initialised==0)
627     {
628         if (dlt_init()<0)
629         {
630             return -1;
631         }
632     }
633
634     if ((appid==0) || (appid[0]=='\0'))
635     {
636         return -1;
637     }
638
639     /* check if application already registered */
640     /* if yes do not register again */
641     if(appid[1]==0)
642     {
643        if(appid[0]==dlt_user.appID[0])
644              return 0;
645     }
646     else if(appid[2]==0)
647     {
648        if(appid[0]==dlt_user.appID[0] &&
649           appid[1]==dlt_user.appID[1])
650              return 0;
651     }
652     else if(appid[3]==0)
653     {
654        if(appid[0]==dlt_user.appID[0] &&
655           appid[1]==dlt_user.appID[1] &&
656           appid[2]==dlt_user.appID[2])
657              return 0;
658     }
659     else
660     {
661        if(appid[0]==dlt_user.appID[0] &&
662           appid[1]==dlt_user.appID[1] &&
663           appid[2]==dlt_user.appID[2] &&
664           appid[3]==dlt_user.appID[3])
665              return 0;
666     }
667
668     DLT_SEM_LOCK();
669
670     /* Store locally application id and application description */
671     dlt_set_id(dlt_user.appID, appid);
672
673     if (dlt_user.application_description!=0)
674     {
675         free(dlt_user.application_description);
676     }
677
678     dlt_user.application_description = 0;
679
680     if (description!=0)
681     {
682         size_t desc_len = strlen(description);
683         dlt_user.application_description= malloc(desc_len+1);
684         if (dlt_user.application_description){
685             strncpy(dlt_user.application_description, description, desc_len);
686
687             /* Terminate transmitted string with 0 */
688             dlt_user.application_description[desc_len]='\0';
689         }
690         else
691         {
692                 DLT_SEM_FREE();
693                 return -1;
694         }
695     }
696
697     DLT_SEM_FREE();
698
699     ret = dlt_user_log_send_register_application();
700
701     return ret;
702 }
703 int dlt_register_context(DltContext *handle, const char *contextid, const char * description)
704 {
705     if (dlt_user_initialised==0)
706     {
707         if (dlt_init()<0)
708         {
709             return -1;
710         }
711     }
712
713     DLT_SEM_LOCK();
714
715     if (dlt_user.appID[0]=='\0')
716     {
717         dlt_log(LOG_ERR, "no application registered!\n");
718
719         DLT_SEM_FREE();
720         return -1;
721     }
722
723     if ((contextid==0) || (contextid[0]=='\0'))
724     {
725         DLT_SEM_FREE();
726         return -1;
727     }
728
729     DLT_SEM_FREE();
730
731     return dlt_register_context_ll_ts(handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET);
732 }
733
734 int dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const char * description, int loglevel, int tracestatus)
735 {
736     DltContextData log;
737     uint32_t i;
738
739     if (dlt_user_initialised==0)
740     {
741         if (dlt_init()<0)
742         {
743             return -1;
744         }
745     }
746
747     DLT_SEM_LOCK();
748
749     if (dlt_user.appID[0]=='\0')
750     {
751         dlt_log(LOG_ERR, "no application registered!\n");
752
753         DLT_SEM_FREE();
754         return -1;
755     }
756
757     DLT_SEM_FREE();
758
759     if ((contextid==0) || (contextid[0]=='\0'))
760     {
761         return -1;
762     }
763
764     if ((loglevel<DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel>DLT_LOG_VERBOSE) || (loglevel==DLT_LOG_DEFAULT))
765     {
766         return -1;
767     }
768
769     if ((tracestatus<DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus>DLT_TRACE_STATUS_ON) || (tracestatus==DLT_TRACE_STATUS_DEFAULT))
770     {
771         return -1;
772     }
773
774     if (dlt_user_log_init(handle, &log)==-1)
775     {
776         return -1;
777     }
778
779     /* Reset message counter */
780     handle->mcnt = 0;
781
782     /* Store context id in log level/trace status field */
783
784     /* Check if already registered, else register context */
785     DLT_SEM_LOCK();
786
787     /* Check of double context registration removed */
788     /* Double registration is already checked by daemon */
789
790         /* Allocate or expand context array */
791         if (dlt_user.dlt_ll_ts == 0)
792         {
793                 dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*DLT_USER_CONTEXT_ALLOC_SIZE);
794                 if (dlt_user.dlt_ll_ts==0)
795                 {
796                         DLT_SEM_FREE();
797                         return -1;
798                 }
799
800                 dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE;
801
802                 /* Initialize new entries */
803                 for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
804                 {
805                         dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
806
807                         /* At startup, logging and tracing is locally enabled */
808                         /* the correct log level/status is set after received from daemon */
809                         dlt_user.dlt_ll_ts[i].log_level    = DLT_USER_INITIAL_LOG_LEVEL;
810                         dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
811
812                         dlt_user.dlt_ll_ts[i].log_level_ptr    = 0;
813                         dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
814
815                         dlt_user.dlt_ll_ts[i].context_description = 0;
816
817                         dlt_user.dlt_ll_ts[i].injection_table = 0;
818                         dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
819                 }
820         }
821         else
822         {
823                 if ((dlt_user.dlt_ll_ts_num_entries%DLT_USER_CONTEXT_ALLOC_SIZE)==0)
824                 {
825                         /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
826                         dlt_ll_ts_type *old_ll_ts;
827                         uint32_t old_max_entries;
828
829                         old_ll_ts = dlt_user.dlt_ll_ts;
830                         old_max_entries = dlt_user.dlt_ll_ts_max_num_entries;
831
832                         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;
833                         dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*
834                                                                  dlt_user.dlt_ll_ts_max_num_entries);
835                         if (dlt_user.dlt_ll_ts==0)
836                         {
837                                 dlt_user.dlt_ll_ts = old_ll_ts;
838                                 dlt_user.dlt_ll_ts_max_num_entries = old_max_entries;
839                                 DLT_SEM_FREE();
840                                 return -1;
841                         }
842
843                         memcpy(dlt_user.dlt_ll_ts,old_ll_ts,sizeof(dlt_ll_ts_type)*dlt_user.dlt_ll_ts_num_entries);
844                         free(old_ll_ts);
845
846                         /* Initialize new entries */
847                         for (i=dlt_user.dlt_ll_ts_num_entries;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
848                         {
849                                 dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
850
851                                 /* At startup, logging and tracing is locally enabled */
852                                 /* the correct log level/status is set after received from daemon */
853                                 dlt_user.dlt_ll_ts[i].log_level    = DLT_USER_INITIAL_LOG_LEVEL;
854                                 dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
855
856                                 dlt_user.dlt_ll_ts[i].log_level_ptr    = 0;
857                                 dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
858
859                                 dlt_user.dlt_ll_ts[i].context_description = 0;
860
861                                 dlt_user.dlt_ll_ts[i].injection_table = 0;
862                                 dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
863                         }
864                 }
865         }
866
867         /* Store locally context id and context description */
868         dlt_set_id(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].contextID, contextid);
869
870         if (dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description!=0)
871         {
872                 free(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description);
873         }
874
875         dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = 0;
876
877         if (description!=0)
878         {
879                 size_t desc_len = strlen(description);
880                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = malloc(desc_len+1);
881                 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description == 0)
882                 {
883                         DLT_SEM_FREE();
884                         return -1;
885                 }
886
887                 strncpy(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description, description, desc_len);
888
889                 /* Terminate transmitted string with 0 */
890                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description[desc_len]='\0';
891         }
892
893         if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
894         {
895                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr = malloc(sizeof(int8_t));
896                 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
897                 {
898                         DLT_SEM_FREE();
899                         return -1;
900                 }
901         }
902         if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
903         {
904                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr = malloc(sizeof(int8_t));
905                 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
906                 {
907                         DLT_SEM_FREE();
908                         return -1;
909                 }
910         }
911
912         if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
913         {
914                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = loglevel;
915         }
916
917         if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
918         {
919                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
920         }
921
922         /* Prepare transfer struct */
923         //dlt_set_id(log->appID, dlt_user.appID);
924         dlt_set_id(handle->contextID, contextid);
925         handle->log_level_pos = dlt_user.dlt_ll_ts_num_entries;
926
927         handle->log_level_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr;
928         handle->trace_status_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr;
929
930         log.context_description = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description;
931
932         *(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;
933         *(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;
934
935         if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
936         {
937                 log.log_level = loglevel;
938         }
939         else
940         {
941                 log.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
942         }
943
944         if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
945         {
946                 log.trace_status = tracestatus;
947         }
948         else
949         {
950                 log.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
951         }
952
953         dlt_user.dlt_ll_ts_num_entries++;
954
955         DLT_SEM_FREE();
956
957         return dlt_user_log_send_register_context(&log);
958 }
959
960 int dlt_unregister_app(void)
961 {
962     int ret;
963
964     if (dlt_user_initialised==0)
965     {
966         return -1;
967     }
968
969     /* Inform daemon to unregister application and all of its contexts */
970     ret = dlt_user_log_send_unregister_application();
971
972     DLT_SEM_LOCK();
973
974     /* Clear and free local stored application information */
975     dlt_set_id(dlt_user.appID, "");
976
977     if (dlt_user.application_description!=0)
978     {
979         free(dlt_user.application_description);
980     }
981
982     dlt_user.application_description = 0;
983
984     DLT_SEM_FREE();
985
986     return ret;
987 }
988
989 int dlt_unregister_context(DltContext *handle)
990 {
991     DltContextData log;
992     int ret;
993
994     if (dlt_user_initialised==0)
995     {
996         return -1;
997     }
998
999     if (dlt_user_log_init(handle, &log) == -1)
1000     {
1001                 return -1;
1002     }
1003
1004     DLT_SEM_LOCK();
1005
1006     handle->log_level_ptr = 0;
1007     handle->trace_status_ptr = 0;
1008
1009     if (dlt_user.dlt_ll_ts)
1010     {
1011         /* Clear and free local stored context information */
1012         dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, "");
1013
1014         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
1015         dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
1016
1017         if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description!=0)
1018         {
1019             free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
1020         }
1021
1022         if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr!=0)
1023         {
1024             free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr);
1025             dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = 0;
1026         }
1027
1028         if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr!=0)
1029         {
1030             free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr);
1031             dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = 0;
1032         }
1033
1034         dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = 0;
1035
1036         if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table)
1037         {
1038             free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
1039             dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = 0;
1040         }
1041
1042         dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks     = 0;
1043     }
1044
1045     DLT_SEM_FREE();
1046
1047     /* Inform daemon to unregister context */
1048     ret = dlt_user_log_send_unregister_context(&log);
1049
1050     return ret;
1051 }
1052
1053 int dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus)
1054 {
1055     uint32_t i;
1056     int ret;
1057
1058     if (dlt_user_initialised==0)
1059     {
1060         if (dlt_init()<0)
1061         {
1062             return -1;
1063         }
1064     }
1065
1066     /* Removed because of DltLogLevelType and DltTraceStatusType
1067
1068     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
1069     {
1070         return -1;
1071     }
1072
1073     if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
1074     {
1075         return -1;
1076     }
1077
1078     if (dlt_user.dlt_ll_ts==0)
1079     {
1080         return -1;
1081     }
1082
1083     */
1084
1085     DLT_SEM_LOCK();
1086     if (dlt_user.dlt_ll_ts==0)
1087     {
1088         DLT_SEM_FREE();
1089         return -1;
1090     }
1091
1092     /* Update local structures */
1093     for (i=0; i<dlt_user.dlt_ll_ts_num_entries;i++)
1094     {
1095         dlt_user.dlt_ll_ts[i].log_level = loglevel;
1096         dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
1097         if(dlt_user.dlt_ll_ts[i].log_level_ptr)
1098                 *(dlt_user.dlt_ll_ts[i].log_level_ptr) = loglevel;
1099         if(dlt_user.dlt_ll_ts[i].trace_status_ptr)
1100                 *(dlt_user.dlt_ll_ts[i].trace_status_ptr) = tracestatus;
1101     }
1102
1103     DLT_SEM_FREE();
1104
1105     /* Inform DLT server about update */
1106     ret = dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus);
1107
1108     return ret;
1109 }
1110
1111 int dlt_get_log_state()
1112 {
1113         return dlt_user.log_state;
1114 }
1115
1116 int dlt_set_log_mode(DltUserLogMode mode)
1117 {
1118     if (dlt_user_initialised==0)
1119     {
1120         if (dlt_init()<0)
1121         {
1122             return -1;
1123         }
1124     }
1125
1126         return dlt_user_log_send_log_mode(mode);
1127 }
1128
1129 int dlt_forward_msg(void *msgdata,size_t size)
1130 {
1131     DltUserHeader userheader;
1132     DltReturnValue ret;
1133
1134     if ((msgdata==0) || (size==0))
1135     {
1136         return -1;
1137     }
1138
1139     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
1140     {
1141         /* Type of internal user message; same value for Trace messages */
1142         return -1;
1143     }
1144
1145     if (dlt_user.dlt_is_file)
1146     {
1147         /* log to file */
1148         ret = dlt_user_log_out2(dlt_user.dlt_log_handle, msgdata, size, 0, 0);
1149         return ((ret==DLT_RETURN_OK)?0:-1);
1150     }
1151     else
1152     {
1153         /* Reattach to daemon if neccesary */
1154         dlt_user_log_reattach_to_daemon();
1155
1156         if (dlt_user.overflow_counter)
1157         {
1158             if (dlt_user_log_send_overflow()==0)
1159             {
1160                                 sprintf(str,"Buffer full! %u messages discarded!\n",dlt_user.overflow_counter);
1161                                 dlt_log(LOG_ERR, str);
1162                 dlt_user.overflow_counter=0;            }
1163         }
1164
1165         /* log to FIFO */
1166         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
1167                                 &(userheader), sizeof(DltUserHeader),
1168                                 msgdata, size, 0, 0);
1169
1170         /* store message in ringbuffer, if an error has occured */
1171         if (ret!=DLT_RETURN_OK)
1172         {
1173             DLT_SEM_LOCK();
1174
1175             if (dlt_buffer_push3(&(dlt_user.startup_buffer),
1176                                 (unsigned char *)&(userheader), sizeof(DltUserHeader),
1177                                  msgdata, size, 0, 0)==-1)
1178                         {
1179                 if(dlt_user.overflow_counter==0)
1180                 {
1181                         dlt_log(LOG_ERR,"Buffer full! First message discarded!\n");
1182                 }
1183                 ret = DLT_RETURN_BUFFER_FULL;
1184                         }
1185
1186             DLT_SEM_FREE();
1187
1188             if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
1189             {
1190                 ;//dlt_log(LOG_WARNING, "dlt_forward_msg: Failed to queue resending.\n");
1191             }
1192         }
1193
1194         switch (ret)
1195         {
1196         case DLT_RETURN_BUFFER_FULL:
1197         {
1198                 /* Buffer full */
1199             dlt_user.overflow_counter += 1;
1200                 return -1;
1201         }
1202         case DLT_RETURN_PIPE_FULL:
1203         {
1204             /* data could not be written */
1205             return -1;
1206         }
1207         case DLT_RETURN_PIPE_ERROR:
1208         {
1209             /* handle not open or pipe error */
1210             close(dlt_user.dlt_log_handle);
1211             dlt_user.dlt_log_handle = -1;
1212
1213             return -1;
1214         }
1215         case DLT_RETURN_ERROR:
1216         {
1217             /* other error condition */
1218             return -1;
1219         }
1220         case DLT_RETURN_OK:
1221         {
1222                 return 0;
1223         }
1224                 default:
1225                 {
1226                         /* This case should not occur */
1227                         return -1;
1228                 }
1229         }
1230     }
1231
1232     return 0;
1233 }
1234
1235 /* ********************************************************************************************* */
1236
1237 inline int dlt_user_log_write_start(DltContext *handle, DltContextData *log,DltLogLevelType loglevel)
1238 {
1239     return dlt_user_log_write_start_id(handle,log,loglevel,DLT_USER_DEFAULT_MSGID);
1240 }
1241
1242 int dlt_user_log_write_start_id(DltContext *handle, DltContextData *log,DltLogLevelType loglevel, uint32_t messageid)
1243 {
1244         if(dlt_user_initialised==0)
1245         {
1246                 if (dlt_init()<0)
1247                 {
1248                         return -1;
1249                 }
1250         }
1251     if (log==0)
1252     {
1253         return -1;
1254     }
1255
1256     if (dlt_user_log_init(handle, log)==-1)
1257     {
1258                 return -1;
1259     }
1260
1261     if (dlt_user.dlt_ll_ts==0)
1262     {
1263         return -1;
1264     }
1265
1266     if (handle->log_level_ptr && (loglevel<=(int)*(handle->log_level_ptr) ) && (loglevel!=0))
1267     {
1268                 log->args_num = 0;
1269         log->log_level = loglevel;
1270
1271         /* In non-verbose mode, insert message id */
1272         if (dlt_user.verbose_mode==0)
1273         {
1274             if ((sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1275             {
1276                 return -1;
1277             }
1278             /* Write message id */
1279             memcpy(log->buffer,&(messageid),sizeof(uint32_t));
1280             log->size = sizeof(uint32_t);
1281
1282             /* as the message id is part of each message in non-verbose mode,
1283                it doesn't increment the argument counter in extended header (if used) */
1284         }
1285         else log->size=0;
1286         return 1;
1287     }
1288
1289     return -1;
1290 }
1291
1292 int dlt_user_log_write_finish(DltContextData *log)
1293 {
1294     if (log==0)
1295     {
1296         return -1;
1297     }
1298
1299     return dlt_user_log_send_log(log, DLT_TYPE_LOG) < 0 ? -1 : 0;
1300 }
1301
1302 int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length)
1303 {
1304     uint16_t arg_size;
1305     uint32_t type_info;
1306
1307     if (log==0)
1308     {
1309         return -1;
1310     }
1311
1312     if ((log->size+length+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1313     {
1314         return -1;
1315     }
1316
1317     if (dlt_user.verbose_mode)
1318     {
1319         if ((log->size+length+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1320         {
1321             return -1;
1322         }
1323
1324         /* Transmit type information */
1325         type_info = DLT_TYPE_INFO_RAWD;
1326
1327         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1328         log->size += sizeof(uint32_t);
1329
1330     }
1331
1332     /* First transmit length of raw data, then the raw data itself */
1333     arg_size = (uint16_t)length;
1334
1335     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1336     log->size += sizeof(uint16_t);
1337
1338     memcpy((log->buffer)+log->size,data,arg_size);
1339     log->size += arg_size;
1340
1341     log->args_num ++;
1342
1343     return 0;
1344 }
1345
1346 int dlt_user_log_write_float32(DltContextData *log, float32_t data)
1347 {
1348     uint32_t type_info;
1349
1350     if (log==0)
1351     {
1352         return -1;
1353     }
1354
1355     if (sizeof(float32_t)!=4)
1356     {
1357         return -1;
1358     }
1359
1360     if ((log->size+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1361     {
1362         return -1;
1363     }
1364
1365     if (dlt_user.verbose_mode)
1366     {
1367         if ((log->size+sizeof(uint32_t)+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1368         {
1369             return -1;
1370         }
1371
1372         type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
1373
1374         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1375         log->size += sizeof(uint32_t);
1376     }
1377
1378     memcpy((log->buffer)+log->size,&data, sizeof(float32_t));
1379     log->size += sizeof(float32_t);
1380
1381     log->args_num ++;
1382
1383     return 0;
1384 }
1385
1386 int dlt_user_log_write_float64(DltContextData *log, float64_t data)
1387 {
1388     uint32_t type_info;
1389
1390     if (log==0)
1391     {
1392         return -1;
1393     }
1394
1395     if (sizeof(float64_t)!=8)
1396     {
1397         return -1;
1398     }
1399
1400     if ((log->size+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1401     {
1402         return -1;
1403     }
1404
1405     if (dlt_user.verbose_mode)
1406     {
1407         if ((log->size+sizeof(uint32_t)+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1408         {
1409             return -1;
1410         }
1411
1412         type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
1413
1414         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1415         log->size += sizeof(uint32_t);
1416     }
1417
1418     memcpy((log->buffer)+log->size,&data, sizeof(float64_t));
1419     log->size += sizeof(float64_t);
1420
1421     log->args_num ++;
1422
1423     return 0;
1424 }
1425
1426 int dlt_user_log_write_uint( DltContextData *log, unsigned int data)
1427 {
1428     if (log==0)
1429     {
1430         return -1;
1431     }
1432
1433     switch (sizeof(unsigned int))
1434     {
1435     case 1:
1436     {
1437         return dlt_user_log_write_uint8(log, (uint8_t)data);
1438         break;
1439     }
1440     case 2:
1441     {
1442         return dlt_user_log_write_uint16(log, (uint16_t)data);
1443         break;
1444     }
1445     case 4:
1446     {
1447         return dlt_user_log_write_uint32(log, (uint32_t)data);
1448         break;
1449     }
1450     case 8:
1451     {
1452         return dlt_user_log_write_uint64(log, (uint64_t)data);
1453                 break;
1454     }
1455     default:
1456     {
1457         return -1;
1458         break;
1459     }
1460     }
1461
1462     return 0;
1463 }
1464
1465 int dlt_user_log_write_uint8(DltContextData *log, uint8_t data)
1466 {
1467     uint32_t type_info;
1468
1469     if (log==0)
1470     {
1471         return -1;
1472     }
1473
1474     if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1475     {
1476         return -1;
1477     }
1478
1479     if (dlt_user.verbose_mode)
1480     {
1481         if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1482         {
1483             return -1;
1484         }
1485
1486         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
1487
1488         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1489         log->size += sizeof(uint32_t);
1490     }
1491
1492     memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1493     log->size += sizeof(uint8_t);
1494
1495     log->args_num ++;
1496
1497     return 0;
1498 }
1499
1500 int dlt_user_log_write_uint16(DltContextData *log, uint16_t data)
1501 {
1502     uint32_t type_info;
1503
1504     if (log==0)
1505     {
1506         return -1;
1507     }
1508
1509     if ((log->size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1510     {
1511         return -1;
1512     }
1513
1514     if (dlt_user.verbose_mode)
1515     {
1516         if ((log->size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1517         {
1518             return -1;
1519         }
1520
1521         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
1522
1523         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1524         log->size += sizeof(uint32_t);
1525     }
1526
1527     memcpy((log->buffer)+log->size,&data,sizeof(uint16_t));
1528     log->size += sizeof(uint16_t);
1529
1530     log->args_num ++;
1531
1532     return 0;
1533 }
1534
1535 int dlt_user_log_write_uint32(DltContextData *log, uint32_t data)
1536 {
1537     uint32_t type_info;
1538
1539     if (log==0)
1540     {
1541         return -1;
1542     }
1543
1544     if ((log->size+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1545     {
1546         return -1;
1547     }
1548
1549     if (dlt_user.verbose_mode)
1550     {
1551         if ((log->size+sizeof(uint32_t)+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1552         {
1553             return -1;
1554         }
1555
1556         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
1557
1558         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1559         log->size += sizeof(uint32_t);
1560     }
1561
1562     memcpy((log->buffer)+log->size,&data, sizeof(uint32_t));
1563     log->size += sizeof(uint32_t);
1564
1565     log->args_num ++;
1566
1567     return 0;
1568 }
1569
1570 int dlt_user_log_write_uint64(DltContextData *log, uint64_t data)
1571 {
1572     uint32_t type_info;
1573
1574     if (log==0)
1575     {
1576         return -1;
1577     }
1578
1579     if ((log->size+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1580     {
1581         return -1;
1582     }
1583
1584     if (dlt_user.verbose_mode)
1585     {
1586         if ((log->size+sizeof(uint32_t)+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1587         {
1588             return -1;
1589         }
1590
1591         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
1592
1593         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1594         log->size +=sizeof(uint32_t);
1595     }
1596
1597     memcpy((log->buffer)+log->size,&data,sizeof(uint64_t));
1598     log->size += sizeof(uint64_t);
1599
1600     log->args_num ++;
1601
1602     return 0;
1603 }
1604
1605 int dlt_user_log_write_int(DltContextData *log, int data)
1606 {
1607     if (log==0)
1608     {
1609         return -1;
1610     }
1611
1612     switch (sizeof(int))
1613     {
1614     case 1:
1615     {
1616         return dlt_user_log_write_int8(log, (int8_t)data);
1617         break;
1618     }
1619     case 2:
1620     {
1621         return dlt_user_log_write_int16(log, (int16_t)data);
1622         break;
1623     }
1624     case 4:
1625     {
1626         return dlt_user_log_write_int32(log, (int32_t)data);
1627         break;
1628     }
1629     case 8:
1630     {
1631         return dlt_user_log_write_int64(log, (int64_t)data);
1632                 break;
1633     }
1634     default:
1635     {
1636         return -1;
1637         break;
1638     }
1639     }
1640
1641     return 0;
1642 }
1643
1644 int dlt_user_log_write_int8(DltContextData *log, int8_t data)
1645 {
1646     uint32_t type_info;
1647
1648     if (log==0)
1649     {
1650         return -1;
1651     }
1652
1653     if ((log->size+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1654     {
1655         return -1;
1656     }
1657
1658     if (dlt_user.verbose_mode)
1659     {
1660         if ((log->size+sizeof(uint32_t)+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1661         {
1662             return -1;
1663         }
1664
1665         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
1666
1667         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1668         log->size += sizeof(uint32_t);
1669     }
1670
1671     memcpy((log->buffer)+log->size,&data,sizeof(int8_t));
1672     log->size += sizeof(int8_t);
1673
1674     log->args_num ++;
1675
1676     return 0;
1677 }
1678
1679 int dlt_user_log_write_int16(DltContextData *log, int16_t data)
1680 {
1681     uint32_t type_info;
1682
1683     if (log==0)
1684     {
1685         return -1;
1686     }
1687
1688     if ((log->size+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1689     {
1690         return -1;
1691     }
1692
1693     if (dlt_user.verbose_mode)
1694     {
1695         if ((log->size+sizeof(uint32_t)+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1696                 {
1697             return -1;
1698                 }
1699
1700         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
1701
1702         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1703         log->size += sizeof(uint32_t);
1704     }
1705
1706     memcpy((log->buffer)+log->size,&data,sizeof(int16_t));
1707     log->size += sizeof(int16_t);
1708
1709     log->args_num ++;
1710
1711     return 0;
1712 }
1713
1714 int dlt_user_log_write_int32(DltContextData *log, int32_t data)
1715 {
1716     uint32_t type_info;
1717
1718     if (log==0)
1719     {
1720         return -1;
1721     }
1722
1723     if ((log->size+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1724     {
1725         return -1;
1726     }
1727
1728     if (dlt_user.verbose_mode)
1729     {
1730         if ((log->size+sizeof(uint32_t)+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1731         {
1732             return -1;
1733         }
1734
1735         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
1736
1737         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1738         log->size += sizeof(uint32_t);
1739     }
1740
1741     memcpy((log->buffer)+log->size,&data, sizeof(int32_t));
1742     log->size += sizeof(int32_t);
1743
1744     log->args_num ++;
1745
1746     return 0;
1747 }
1748
1749 int dlt_user_log_write_int64(DltContextData *log, int64_t data)
1750 {
1751     uint32_t type_info;
1752
1753     if (log==0)
1754     {
1755         return -1;
1756     }
1757
1758     if ((log->size+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1759     {
1760         return -1;
1761     }
1762
1763     if (dlt_user.verbose_mode)
1764     {
1765         if ((log->size+sizeof(uint32_t)+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1766         {
1767             return -1;
1768         }
1769
1770         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
1771
1772         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1773         log->size += sizeof(uint32_t);
1774     }
1775
1776     memcpy((log->buffer)+log->size,&data,sizeof(int64_t));
1777     log->size += sizeof(int64_t);
1778
1779     log->args_num ++;
1780
1781     return 0;
1782 }
1783
1784 int dlt_user_log_write_bool(DltContextData *log, uint8_t data)
1785 {
1786     uint32_t type_info;
1787
1788     if (log==0)
1789     {
1790         return -1;
1791     }
1792
1793     if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1794     {
1795         return -1;
1796     }
1797
1798     if (dlt_user.verbose_mode)
1799     {
1800         if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1801         {
1802             return -1;
1803         }
1804
1805         type_info = DLT_TYPE_INFO_BOOL;
1806
1807         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1808         log->size += sizeof(uint32_t);
1809     }
1810
1811     memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1812     log->size += sizeof(uint8_t);
1813
1814     log->args_num ++;
1815
1816     return 0;
1817 }
1818
1819 int dlt_user_log_write_string(DltContextData *log, const char *text)
1820 {
1821     uint16_t arg_size;
1822     uint32_t type_info;
1823
1824     if ((log==0) || (text==0))
1825     {
1826         return -1;
1827     }
1828
1829     if ((log->size+(strlen(text)+1)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1830     {
1831         return -1;
1832     }
1833
1834     if (dlt_user.verbose_mode)
1835     {
1836         if ((log->size+(strlen(text)+1)+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1837         {
1838             return -1;
1839         }
1840
1841         type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII;
1842
1843         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1844         log->size += sizeof(uint32_t);
1845     }
1846
1847     arg_size = strlen(text) + 1;
1848
1849     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1850     log->size += sizeof(uint16_t);
1851
1852     memcpy((log->buffer)+log->size,text,arg_size);
1853     log->size += arg_size;
1854
1855     log->args_num ++;
1856
1857     return 0;
1858 }
1859
1860 int dlt_user_log_write_utf8_string(DltContextData *log, const char *text)
1861 {
1862     uint16_t arg_size;
1863     uint32_t type_info;
1864
1865     if ((log==0) || (text==0))
1866     {
1867         return -1;
1868     }
1869
1870     arg_size = strlen(text)+1;
1871
1872     if ((log->size+arg_size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1873     {
1874         return -1;
1875     }
1876
1877     if (dlt_user.verbose_mode)
1878     {
1879         if ((log->size+arg_size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1880         {
1881             return -1;
1882         }
1883
1884         type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8;
1885
1886         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1887         log->size += sizeof(uint32_t);
1888     }
1889
1890     arg_size = strlen(text) + 1;
1891
1892     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1893     log->size += sizeof(uint16_t);
1894
1895     memcpy((log->buffer)+log->size,text,arg_size);
1896     log->size += arg_size;
1897
1898     log->args_num ++;
1899
1900     return 0;
1901 }
1902
1903 int dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
1904                                     int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length))
1905 {
1906     DltContextData log;
1907     uint32_t i,j,k;
1908     int found = 0;
1909
1910         DltUserInjectionCallback *old;
1911
1912     if (handle==0)
1913     {
1914         return -1;
1915     }
1916
1917     if (dlt_user_log_init(handle, &log)==-1)
1918     {
1919                 return -1;
1920     }
1921
1922     if (service_id<DLT_USER_INJECTION_MIN)
1923     {
1924         return -1;
1925     }
1926     /* This function doesn't make sense storing to local file is choosen;
1927        so terminate this function */
1928     if (dlt_user.dlt_is_file)
1929     {
1930         return 0;
1931     }
1932
1933     DLT_SEM_LOCK();
1934
1935     if (dlt_user.dlt_ll_ts==0)
1936     {
1937         DLT_SEM_FREE();
1938         return 0;
1939     }
1940
1941     /* Insert callback in corresponding table */
1942     i=handle->log_level_pos;
1943
1944     /* Insert each service_id only once */
1945     for (k=0;k<dlt_user.dlt_ll_ts[i].nrcallbacks;k++)
1946     {
1947         if ((dlt_user.dlt_ll_ts[i].injection_table) &&
1948                 (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id))
1949         {
1950             found = 1;
1951             break;
1952         }
1953     }
1954
1955     if (found)
1956     {
1957         j = k;
1958     }
1959     else
1960     {
1961         j=dlt_user.dlt_ll_ts[i].nrcallbacks;
1962
1963         /* Allocate or expand injection table */
1964         if (dlt_user.dlt_ll_ts[i].injection_table == 0)
1965         {
1966             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback));
1967             if(dlt_user.dlt_ll_ts[i].injection_table == 0)
1968             {
1969                 DLT_SEM_FREE();
1970                 return -1;
1971             }
1972         }
1973         else
1974         {
1975             old = dlt_user.dlt_ll_ts[i].injection_table;
1976             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback)*(j+1));
1977             if(dlt_user.dlt_ll_ts[i].injection_table == 0)
1978             {
1979                 dlt_user.dlt_ll_ts[i].injection_table = old;
1980                 DLT_SEM_FREE();
1981                 return -1;
1982             }
1983             memcpy(dlt_user.dlt_ll_ts[i].injection_table,old,sizeof(DltUserInjectionCallback)*j);
1984             free(old);
1985         }
1986
1987         dlt_user.dlt_ll_ts[i].nrcallbacks++;
1988     }
1989
1990     /* Store service_id and corresponding function pointer for callback function */
1991     dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id;
1992     dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = dlt_injection_callback;
1993
1994     DLT_SEM_FREE();
1995     return 0;
1996 }
1997
1998 /**
1999  * NW Trace related
2000  */
2001
2002
2003 int check_buffer()
2004 {
2005         int total_size, used_size;
2006         dlt_user_check_buffer(&total_size, &used_size);
2007
2008         if((total_size - used_size) < (total_size/2))
2009         {
2010                 return -1;
2011         }
2012         return 1;
2013 }
2014
2015 /**
2016  * Send the start of a segment chain.
2017  * Returns -1 on failure
2018  */
2019 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)
2020 {
2021
2022     DltContextData log;
2023         struct timeval tv;
2024
2025     if (handle==NULL)
2026     {
2027         return -1;
2028     }
2029
2030     if (dlt_user_log_init(handle, &log)==-1)
2031     {
2032                 return -1;
2033     }
2034
2035
2036     if (dlt_user.dlt_ll_ts==0)
2037     {
2038         return -1;
2039     }
2040
2041     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2042     {
2043
2044         log.args_num = 0;
2045         log.trace_status = nw_trace_type;
2046         log.size = 0;
2047
2048         gettimeofday(&tv, NULL);
2049         *id = tv.tv_usec;
2050
2051         /* Write identifier */
2052         if(dlt_user_log_write_string(&log, "NWST") < 0)
2053         {
2054                 return -1;
2055         }
2056
2057         /* Write stream handle */
2058         if(dlt_user_log_write_uint16(&log, *id) < 0)
2059         {
2060                 return -1;
2061         }
2062
2063         /* Write header */
2064         if(dlt_user_log_write_raw(&log, header, header_len) < 0)
2065         {
2066                 return -1;
2067         }
2068
2069         /* Write size of payload */
2070         if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2071         {
2072                 return -1;
2073         }
2074
2075         /* Write expected segment count */
2076         uint16_t segment_count = payload_len/DLT_MAX_TRACE_SEGMENT_SIZE+1;
2077
2078         /* If segments align perfectly with segment size, avoid sending empty segment */
2079         if((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0)
2080         {
2081                 segment_count--;
2082         }
2083
2084         if(dlt_user_log_write_uint16(&log, segment_count) < 0)
2085         {
2086                 return -1;
2087         }
2088
2089         /* Write length of one segment */
2090         if(dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0)
2091         {
2092                 return -1;
2093         }
2094
2095         /* Send log */
2096         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2097     }
2098     return 0;
2099 }
2100
2101 int dlt_user_trace_network_segmented_segment(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
2102 {
2103         while(check_buffer() < 0)
2104         {
2105                 usleep(1000*50); // Wait 50ms
2106                 dlt_user_log_resend_buffer();
2107         }
2108
2109     if (handle==NULL)
2110     {
2111         return -1;
2112     }
2113
2114     DltContextData log;
2115
2116     if (dlt_user_log_init(handle, &log)==-1)
2117     {
2118                 return -1;
2119     }
2120
2121     if (dlt_user.dlt_ll_ts==0)
2122     {
2123         return -1;
2124     }
2125
2126     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2127     {
2128
2129         log.args_num = 0;
2130         log.trace_status = nw_trace_type;
2131         log.size = 0;
2132
2133         /* Write identifier */
2134         if(dlt_user_log_write_string(&log, "NWCH") < 0)
2135         {
2136                 return -1;
2137         }
2138
2139         /* Write stream handle */
2140         if(dlt_user_log_write_uint16(&log, id) < 0)
2141         {
2142                 return -1;
2143         }
2144
2145         /* Write segment sequence number */
2146         if(dlt_user_log_write_uint16(&log, sequence) < 0)
2147         {
2148                 return -1;
2149         }
2150
2151         /* Write data */
2152         if(dlt_user_log_write_raw(&log, payload, payload_len) < 0)
2153         {
2154                 return -1;
2155         }
2156
2157         /* Send log */
2158         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2159     }
2160
2161     /* Allow other threads to log between chunks */
2162         pthread_yield();
2163     return 0;
2164 }
2165
2166 int dlt_user_trace_network_segmented_end(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type)
2167 {
2168     DltContextData log;
2169
2170     if (handle==0)
2171     {
2172         return -1;
2173     }
2174
2175     if (dlt_user_log_init(handle, &log)==-1)
2176     {
2177                 return -1;
2178     }
2179
2180
2181
2182     if (dlt_user.dlt_ll_ts==0)
2183     {
2184         return -1;
2185     }
2186
2187     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2188     {
2189
2190         log.args_num = 0;
2191         log.trace_status = nw_trace_type;
2192         log.size = 0;
2193
2194         /* Write identifier */
2195         if(dlt_user_log_write_string(&log, "NWEN") < 0)
2196         {
2197                 return -1;
2198         }
2199
2200         /* Write stream handle */
2201         if(dlt_user_log_write_uint(&log, id) < 0)
2202         {
2203                 return -1;
2204         }
2205
2206         /* Send log */
2207         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2208     }
2209     return 0;
2210 }
2211
2212
2213 void dlt_user_trace_network_segmented_thread(void *unused)
2214 {
2215         /* Unused on purpose. */
2216         (void) unused;
2217
2218     prctl(PR_SET_NAME, "dlt_segmented", 0, 0, 0);
2219
2220         s_segmented_data *data;
2221
2222         while(1)
2223         {
2224                 // Wait until message queue is initialized
2225                 pthread_mutex_lock(&mq_mutex);
2226                 if(dlt_user.dlt_segmented_queue_read_handle < 0)
2227                 {
2228                         pthread_cond_wait(&mq_init_condition, &mq_mutex);
2229                 }
2230                 pthread_mutex_unlock(&mq_mutex);
2231
2232                 ssize_t read = mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char *)&data,
2233                                         sizeof(s_segmented_data * ), NULL);
2234
2235                 if(read != sizeof(s_segmented_data *))
2236                 {
2237
2238                         char str[255];
2239                         snprintf(str,254,"NWTSegmented: Error while reading queue: %s \n",strerror(errno));
2240                         dlt_log(LOG_CRIT, str);
2241                         continue;
2242                 }
2243
2244                 /* Indicator just to try to flush the buffer */
2245                 if(data->payload_len == DLT_DELAYED_RESEND_INDICATOR_PATTERN)
2246                 {
2247                         // Sleep 100ms, to allow other process to read FIFO
2248                         usleep(100*1000);
2249                         if(dlt_user_log_resend_buffer() < 0)
2250                         {
2251                                 // Requeue if still not empty
2252                                 if ( dlt_user_queue_resend() < 0 )
2253                                 {
2254                                     //dlt_log(LOG_WARNING, "Failed to queue resending in dlt_user_trace_network_segmented_thread.\n");
2255                                 }
2256                         }
2257                         free(data);
2258                         continue;
2259                 }
2260
2261                 dlt_user_trace_network_segmented_thread_segmenter(data);
2262
2263                 /* Send the end message */
2264                 DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type);
2265                 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2266                 {
2267                         dlt_log(LOG_ERR,"NWTSegmented: Could not send end segment.\n");
2268                 }
2269
2270                 /* Free resources */
2271                 free(data->header);
2272                 free(data->payload);
2273                 free(data);
2274         }
2275 }
2276
2277 void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data)
2278 {
2279         /* Segment the data and send the chunks */
2280         void *ptr                       = NULL;
2281         uint16_t offset         = 0;
2282         uint16_t sequence       = 0;
2283         do
2284         {
2285                 uint16_t len = 0;
2286                 if(offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len)
2287                 {
2288                         len = data->payload_len - offset;
2289                 }
2290                 else
2291                 {
2292                         len = DLT_MAX_TRACE_SEGMENT_SIZE;
2293                 }
2294                 /* If payload size aligns perfectly with segment size, avoid sending empty segment */
2295                 if(len == 0)
2296                 {
2297                         break;
2298                 }
2299
2300                 ptr = data->payload + offset;
2301                 DltReturnValue err = dlt_user_trace_network_segmented_segment(data->id, data->handle, data->nw_trace_type, sequence++, len, ptr);
2302                 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2303                 {
2304                         dlt_log(LOG_ERR,"NWTSegmented: Could not send segment. Aborting.\n");
2305                         break; // loop
2306                 }
2307                 offset += len;
2308         }while(ptr < data->payload + data->payload_len);
2309 }
2310
2311
2312 int dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2313 {
2314         /* Send as normal trace if possible */
2315         if(header_len+payload_len+sizeof(uint16_t) < DLT_USER_BUF_MAX_SIZE) {
2316                 return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload);
2317         }
2318
2319         /* Allocate Memory */
2320         s_segmented_data *thread_data = malloc(sizeof(s_segmented_data));
2321         if(thread_data == NULL)
2322         {
2323                 return -1;
2324         }
2325         thread_data->header = malloc(header_len);
2326         if(thread_data->header == NULL)
2327         {
2328                 free(thread_data);
2329                 return -1;
2330         }
2331         thread_data->payload = malloc(payload_len);
2332         if(thread_data->payload == NULL)
2333         {
2334                 free(thread_data->header);
2335                 free(thread_data);
2336                 return -1;
2337         }
2338
2339         /* Copy data */
2340         thread_data->handle = handle;
2341         thread_data->nw_trace_type = nw_trace_type;
2342         thread_data->header_len = header_len;
2343         memcpy(thread_data->header, header, header_len);
2344         thread_data->payload_len = payload_len;
2345         memcpy(thread_data->payload, payload, payload_len);
2346
2347         /* Send start message */
2348         DltReturnValue err =    dlt_user_trace_network_segmented_start(&(thread_data->id),
2349                                                         thread_data->handle, thread_data->nw_trace_type,
2350                                                         thread_data->header_len, thread_data->header,
2351                                                         thread_data->payload_len);
2352         if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2353         {
2354                 dlt_log(LOG_ERR,"NWTSegmented: Could not send start segment. Aborting.\n");
2355                 free(thread_data->header);
2356                 free(thread_data->payload);
2357                 free(thread_data);
2358                 return -1;
2359         }
2360
2361         /* Open queue if it is not open */
2362         if(dlt_init_message_queue() < 0)
2363         {
2364                 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2365                 free(thread_data->header);
2366                 free(thread_data->payload);
2367                 free(thread_data);
2368
2369                 return -1;
2370         }
2371
2372         /* Add to queue */
2373         if(mq_send(dlt_user.dlt_segmented_queue_write_handle,
2374                         (char *)&thread_data, sizeof(s_segmented_data *), 1) < 0)
2375         {
2376                 if(errno == EAGAIN)
2377                 {
2378                         dlt_log(LOG_ERR, "NWTSegmented: Queue full. Message discarded.\n");
2379                 }
2380                 free(thread_data->header);
2381                 free(thread_data->payload);
2382                 free(thread_data);              
2383         char str[256];
2384         snprintf(str,255,"NWTSegmented: Could not write into queue: %s \n",strerror(errno));
2385         dlt_log(LOG_CRIT, str);
2386                 return -1;
2387         }
2388
2389         //thread_data will be freed by the receiver function
2390         //coverity[leaked_storage]
2391         return 0;
2392 }
2393
2394 int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2395 {
2396         return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1);
2397 }
2398
2399 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)
2400 {
2401     DltContextData log;
2402
2403     if (dlt_user_initialised==0)
2404     {
2405         if (dlt_init()<0)
2406         {
2407             return -1;
2408         }
2409     }
2410
2411     if (dlt_user_log_init(handle, &log)==-1)
2412     {
2413                 return -1;
2414     }
2415
2416     if (handle==0)
2417     {
2418         return -1;
2419     }
2420
2421     /* Commented out because of DltNetworkTraceType:
2422
2423     if ((nw_trace_type<=0) || (nw_trace_type>0x15))
2424     {
2425         return -1;
2426     }
2427
2428     */
2429
2430     if (dlt_user.dlt_ll_ts==0)
2431     {
2432         return -1;
2433     }
2434
2435     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2436     {
2437
2438         log.args_num = 0;
2439         log.trace_status = nw_trace_type;
2440         log.size = 0;
2441
2442         if (header==0)
2443         {
2444             header_len=0;
2445         }
2446
2447         /* If truncation is allowed, check if we must do it */
2448         if(allow_truncate > 0 && (header_len+payload_len+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
2449         {
2450                 /* Identify as truncated */
2451                 if(dlt_user_log_write_string(&log, "NWTR") < 0)
2452                 {
2453                         return -1;
2454                 }
2455
2456             /* Write header and its length */
2457             if (dlt_user_log_write_raw(&log, header, header_len) < 0)
2458             {
2459                 return -1;
2460             }
2461
2462                 /* Write original size of payload */
2463             if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2464             {
2465                 return -1;
2466             }
2467
2468                 /**
2469                  *  Calculate maximum avaialble space in sending buffer after headers.
2470                  */
2471
2472                 int truncated_payload_len = DLT_USER_BUF_MAX_SIZE -
2473                                 log.size - sizeof(uint16_t) - sizeof(uint32_t);
2474
2475             /* Write truncated payload */
2476             if (dlt_user_log_write_raw(&log, payload, truncated_payload_len) < 0)
2477             {
2478                         return -1;
2479             }
2480         }
2481         else /* Truncation not allowed or data short enough */
2482         {
2483             /* Write header and its length */
2484             if (dlt_user_log_write_raw(&log, header, header_len)==-1)
2485             {
2486                 return -1;
2487             }
2488
2489             if (payload==0)
2490             {
2491                 payload_len=0;
2492             }
2493
2494             /* Write payload and its length */
2495             if (dlt_user_log_write_raw(&log, payload, payload_len)==-1)
2496             {
2497                         return -1;
2498             }
2499         }
2500
2501         /* Send log */
2502         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2503     }
2504
2505     return 0;
2506 }
2507
2508 int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
2509 {
2510     DltContextData log;
2511
2512     if (dlt_user.verbose_mode==0)
2513     {
2514         return -1;
2515     }
2516
2517     if ((handle==0) || (text==0))
2518     {
2519         return -1;
2520     }
2521
2522     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2523     {
2524         if (dlt_user_log_write_string(&log,text)==-1)
2525         {
2526                         return -1;
2527         }
2528         if (dlt_user_log_write_finish(&log)==-1)
2529         {
2530                 return -1;
2531         }
2532     }
2533
2534     return 0;
2535 }
2536
2537 int dlt_log_string_int(DltContext *handle,DltLogLevelType loglevel, const char *text, int data)
2538 {
2539     DltContextData log;
2540
2541     if (dlt_user.verbose_mode==0)
2542     {
2543         return -1;
2544     }
2545
2546     if ((handle==0) || (text==0))
2547     {
2548         return -1;
2549     }
2550
2551     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2552     {
2553         if (dlt_user_log_write_string(&log,text)==-1)
2554         {
2555                         return -1;
2556         }
2557         if (dlt_user_log_write_int(&log,data)==-1)
2558         {
2559                         return -1;
2560         }
2561         if (dlt_user_log_write_finish(&log)==-1)
2562         {
2563                         return -1;
2564         }
2565     }
2566
2567     return 0;
2568 }
2569
2570 int dlt_log_string_uint(DltContext *handle,DltLogLevelType loglevel, const char *text, unsigned int data)
2571 {
2572     DltContextData log;
2573
2574     if (dlt_user.verbose_mode==0)
2575     {
2576         return -1;
2577     }
2578
2579     if ((handle==0) || (text==0))
2580     {
2581         return -1;
2582     }
2583
2584     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2585     {
2586         if (dlt_user_log_write_string(&log,text)==-1)
2587         {
2588                         return -1;
2589         }
2590         if (dlt_user_log_write_uint(&log,data)==-1)
2591         {
2592                         return -1;
2593         }
2594         if (dlt_user_log_write_finish(&log)==-1)
2595         {
2596                         return -1;
2597         }
2598     }
2599
2600     return 0;
2601 }
2602
2603 int dlt_log_int(DltContext *handle,DltLogLevelType loglevel, int data)
2604 {
2605     DltContextData log;
2606
2607     if (dlt_user.verbose_mode==0)
2608     {
2609         return -1;
2610     }
2611
2612     if (handle==0)
2613     {
2614         return -1;
2615     }
2616
2617     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2618     {
2619         if (dlt_user_log_write_int(&log,data)==-1)
2620         {
2621                         return -1;
2622         }
2623         if (dlt_user_log_write_finish(&log)==-1)
2624         {
2625                         return -1;
2626         }
2627     }
2628
2629     return 0;
2630 }
2631
2632 int dlt_log_uint(DltContext *handle,DltLogLevelType loglevel, unsigned int data)
2633 {
2634     DltContextData log;
2635
2636     if (dlt_user.verbose_mode==0)
2637     {
2638         return -1;
2639     }
2640
2641     if (handle==0)
2642     {
2643         return -1;
2644     }
2645
2646     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2647     {
2648         if (dlt_user_log_write_uint(&log,data)==-1)
2649         {
2650                         return -1;
2651         }
2652         if (dlt_user_log_write_finish(&log)==-1)
2653         {
2654                         return -1;
2655         }
2656     }
2657
2658     return 0;
2659 }
2660
2661 int dlt_log_raw(DltContext *handle,DltLogLevelType loglevel, void *data,uint16_t length)
2662 {
2663     DltContextData log;
2664
2665     if (dlt_user.verbose_mode==0)
2666     {
2667         return -1;
2668     }
2669
2670     if (handle==0)
2671     {
2672         return -1;
2673     }
2674
2675     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2676     {
2677         if (dlt_user_log_write_raw(&log,data,length)==-1)
2678         {
2679                         return -1;
2680         }
2681         if (dlt_user_log_write_finish(&log)==-1)
2682         {
2683                         return -1;
2684         }
2685     }
2686
2687     return 0;
2688 }
2689
2690 int dlt_verbose_mode(void)
2691 {
2692     if (dlt_user_initialised==0)
2693     {
2694         if (dlt_init()<0)
2695         {
2696             return -1;
2697         }
2698     }
2699
2700     /* Switch to verbose mode */
2701     dlt_user.verbose_mode = 1;
2702
2703     return 0;
2704 }
2705
2706 int dlt_nonverbose_mode(void)
2707 {
2708     if (dlt_user_initialised==0)
2709     {
2710         if (dlt_init()<0)
2711         {
2712             return -1;
2713         }
2714     }
2715
2716     /* Switch to non-verbose mode */
2717     dlt_user.verbose_mode = 0;
2718
2719     return 0;
2720 }
2721
2722 int dlt_enable_local_print(void)
2723 {
2724     if (dlt_user_initialised==0)
2725     {
2726         if (dlt_init()<0)
2727         {
2728             return -1;
2729         }
2730     }
2731
2732     dlt_user.enable_local_print = 1;
2733
2734     return 0;
2735 }
2736
2737 int dlt_disable_local_print(void)
2738 {
2739     if (dlt_user_initialised==0)
2740     {
2741         if (dlt_init()<0)
2742         {
2743             return -1;
2744         }
2745     }
2746
2747     dlt_user.enable_local_print = 0;
2748
2749     return 0;
2750 }
2751
2752 void dlt_user_receiverthread_function(__attribute__((unused)) void *ptr)
2753 {
2754     prctl(PR_SET_NAME, "dlt_receiver", 0, 0, 0);
2755     while (1)
2756     {
2757         /* Check for new messages from DLT daemon */
2758         if (dlt_user_log_check_user_message()==-1)
2759         {
2760                         /* Critical error */
2761                         dlt_log(LOG_CRIT,"Receiver thread encountered error condition\n");
2762         }
2763
2764         usleep(DLT_USER_RECEIVE_DELAY); /* delay */
2765     }
2766 }
2767
2768 /* Private functions of user library */
2769
2770 int dlt_user_log_init(DltContext *handle, DltContextData *log)
2771 {
2772     if (dlt_user_initialised==0)
2773     {
2774         if (dlt_init()<0)
2775         {
2776             return -1;
2777         }
2778     }
2779
2780     log->handle = handle;
2781
2782     return 0;
2783 }
2784
2785 int dlt_user_queue_resend(void)
2786 {
2787         static unsigned char dlt_user_queue_resend_error_counter = 0;
2788
2789         if(dlt_user.dlt_log_handle < 0)
2790         {
2791                 // Fail silenty. FIFO is not open yet
2792                 return -1;
2793         }
2794     /**
2795      * Ask segmented thread to try emptying the buffer soon.
2796      * This will be freed in dlt_user_trace_network_segmented_thread
2797      * */
2798     s_segmented_data *resend_data = malloc(sizeof(s_segmented_data));
2799
2800     if (NULL == resend_data)
2801     {
2802         return -1;
2803     }
2804
2805     resend_data->payload_len = DLT_DELAYED_RESEND_INDICATOR_PATTERN;
2806
2807
2808
2809     /* Open queue if it is not open */
2810         if(dlt_init_message_queue() < 0)
2811         {
2812         if(!dlt_user_queue_resend_error_counter)
2813         {
2814                 // log error only when problem occurred first time
2815                 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2816         }
2817         dlt_user_queue_resend_error_counter = 1;
2818         free(resend_data);
2819                 return -1;
2820         }
2821
2822     if(mq_send(dlt_user.dlt_segmented_queue_write_handle, (char *)&resend_data, sizeof(s_segmented_data *), 1) < 0)
2823     {
2824         if(!dlt_user_queue_resend_error_counter)
2825         {
2826                 // log error only when problem occurred first time
2827                         char str[255];
2828                         snprintf(str,254,"Could not request resending.: %s \n",strerror(errno));
2829                         dlt_log(LOG_CRIT, str);
2830         }
2831         dlt_user_queue_resend_error_counter = 1;
2832         free(resend_data);
2833         return -1;
2834     }
2835
2836     dlt_user_queue_resend_error_counter = 0;
2837
2838     //thread_data will be freed by the receiver function
2839     //coverity[leaked_storage]
2840     return 0;
2841 }
2842
2843 DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype)
2844 {
2845     DltMessage msg;
2846     DltUserHeader userheader;
2847     int32_t len;
2848
2849     DltReturnValue ret = DLT_RETURN_OK;
2850
2851     if (log==0)
2852     {
2853         return DLT_RETURN_ERROR;
2854     }
2855
2856     if (log->handle==0)
2857     {
2858         return DLT_RETURN_ERROR;
2859     }
2860
2861     if (dlt_user.appID[0]=='\0')
2862     {
2863         return DLT_RETURN_ERROR;
2864     }
2865
2866     if (log->handle->contextID[0]=='\0')
2867     {
2868         return DLT_RETURN_ERROR;
2869     }
2870
2871     if ((mtype<DLT_TYPE_LOG) || (mtype>DLT_TYPE_CONTROL))
2872     {
2873         return DLT_RETURN_ERROR;
2874     }
2875
2876     /* also for Trace messages */
2877 #ifdef DLT_SHM_ENABLE
2878     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_SHM)==-1)
2879 #else
2880     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
2881 #endif
2882     {
2883                 return DLT_RETURN_ERROR;
2884     }
2885
2886     if (dlt_message_init(&msg,0)==-1)
2887     {
2888         return DLT_RETURN_ERROR;
2889     }
2890
2891     msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
2892
2893     if (dlt_set_storageheader(msg.storageheader,dlt_user.ecuID)==-1)
2894     {
2895                 return DLT_RETURN_ERROR;
2896     }
2897
2898     msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
2899     msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_PROTOCOL_VERSION1 ;
2900
2901     if (dlt_user.verbose_mode)
2902     {
2903         /* In verbose mode, send extended header */
2904         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2905     }
2906     else
2907     {
2908         /* In non-verbose, send extended header if desired */
2909 #if (DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE==1)
2910         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2911 #endif
2912     }
2913
2914 #if (BYTE_ORDER==BIG_ENDIAN)
2915     msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
2916 #endif
2917
2918     msg.standardheader->mcnt = log->handle->mcnt++;
2919
2920     /* Set header extra parameters */
2921     dlt_set_id(msg.headerextra.ecu,dlt_user.ecuID);
2922     //msg.headerextra.seid = 0;
2923     msg.headerextra.tmsp = dlt_uptime();
2924
2925     if (dlt_message_set_extraparameters(&msg,0)==-1)
2926     {
2927         return DLT_RETURN_ERROR;
2928     }
2929
2930     /* Fill out extended header, if extended header should be provided */
2931     if (DLT_IS_HTYP_UEH(msg.standardheader->htyp))
2932     {
2933         /* with extended header */
2934         msg.extendedheader = (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)  );
2935
2936         switch (mtype)
2937         {
2938         case DLT_TYPE_LOG:
2939         {
2940             msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2941             break;
2942         }
2943         case DLT_TYPE_NW_TRACE:
2944         {
2945             msg.extendedheader->msin = (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT) | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2946             break;
2947         }
2948         default:
2949         {
2950                     /* This case should not occur */
2951             return DLT_RETURN_ERROR;
2952             break;
2953         }
2954         }
2955
2956         /* If in verbose mode, set flag in header for verbose mode */
2957         if (dlt_user.verbose_mode)
2958         {
2959             msg.extendedheader->msin |= DLT_MSIN_VERB;
2960         }
2961
2962         msg.extendedheader->noar = log->args_num;              /* number of arguments */
2963         dlt_set_id(msg.extendedheader->apid,dlt_user.appID);       /* application id */
2964         dlt_set_id(msg.extendedheader->ctid,log->handle->contextID);   /* context id */
2965
2966         msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2967     }
2968     else
2969     {
2970         /* without extended header */
2971         msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2972     }
2973
2974     len=msg.headersize - sizeof(DltStorageHeader) +log->size;
2975     if (len>UINT16_MAX)
2976     {
2977         dlt_log(LOG_CRIT,"Huge message discarded!\n");
2978         return DLT_RETURN_ERROR;
2979     }
2980
2981     msg.standardheader->len = DLT_HTOBE_16(len);
2982
2983     /* print to std out, if enabled */
2984     if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) &&
2985             (dlt_user.local_print_mode != DLT_PM_AUTOMATIC))
2986     {
2987         if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
2988         {
2989             if (dlt_user_print_msg(&msg, log)==-1)
2990             {
2991                                 return DLT_RETURN_ERROR;
2992             }
2993         }
2994     }
2995
2996     if (dlt_user.dlt_is_file)
2997     {
2998         /* log to file */
2999         ret=dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size);
3000         return ret;
3001     }
3002     else
3003     {
3004         /* Reattach to daemon if neccesary */
3005         dlt_user_log_reattach_to_daemon();
3006
3007         if (dlt_user.overflow_counter)
3008         {
3009             if (dlt_user_log_send_overflow()==0)
3010             {
3011                                 sprintf(str,"%u messages discarded!\n",dlt_user.overflow_counter);
3012                                 dlt_log(LOG_ERR, str);
3013                 dlt_user.overflow_counter=0;
3014             }
3015         }
3016
3017                 /* try to resent old data first */
3018                 ret = DLT_RETURN_OK;
3019                 if(dlt_user.dlt_log_handle!=-1)
3020                         ret = dlt_user_log_resend_buffer();
3021                 if(ret==DLT_RETURN_OK)
3022                 {
3023                         /* resend ok or nothing to resent */
3024 #ifdef DLT_SHM_ENABLE
3025                         if(dlt_user.dlt_log_handle!=-1)
3026                                 dlt_shm_push(&dlt_user.dlt_shm,msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3027                                                                                         log->buffer, log->size,0,0);                   
3028
3029                         /* log to FIFO */
3030                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
3031                                                                         &(userheader), sizeof(DltUserHeader),
3032                                                                         0, 0,
3033                                                                         0, 0);
3034 #else
3035                         /* log to FIFO */
3036 #ifdef DLT_TEST_ENABLE
3037                         if(dlt_user.corrupt_user_header) {
3038                                 userheader.pattern[0]=0xff;
3039                                 userheader.pattern[1]=0xff;
3040                                 userheader.pattern[2]=0xff;
3041                                 userheader.pattern[3]=0xff;
3042                         }
3043                         if(dlt_user.corrupt_message_size) {
3044                                 msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
3045                         }
3046 #endif
3047                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
3048                                                                         &(userheader), sizeof(DltUserHeader),
3049                                                                         msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3050                                                                         log->buffer, log->size);                
3051 #endif                  
3052                 }
3053                 
3054         /* store message in ringbuffer, if an error has occured */
3055         if (ret!=DLT_RETURN_OK)
3056         {
3057             DLT_SEM_LOCK();
3058
3059             if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3060                                 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3061                                 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3062                                 log->buffer, log->size)==-1)
3063                         {
3064                 if(dlt_user.overflow_counter==0)
3065                 {
3066
3067                         dlt_log(LOG_ERR,"Buffer full! Messages will be discarded.\n");
3068                 }
3069                 ret = DLT_RETURN_BUFFER_FULL;
3070                         }
3071
3072             DLT_SEM_FREE();
3073
3074                 // Fail silenty if FIFO is not open
3075             if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3076             {
3077                 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_log: Failed to queue resending.\n");
3078             }
3079         }
3080
3081         switch (ret)
3082         {
3083         case DLT_RETURN_BUFFER_FULL:
3084         {
3085                 /* Buffer full */
3086             dlt_user.overflow_counter += 1;
3087                 return DLT_RETURN_BUFFER_FULL;
3088         }
3089         case DLT_RETURN_PIPE_FULL:
3090         {
3091             /* data could not be written */
3092             return DLT_RETURN_PIPE_FULL;
3093         }
3094         case DLT_RETURN_PIPE_ERROR:
3095         {
3096             /* handle not open or pipe error */
3097             close(dlt_user.dlt_log_handle);
3098             dlt_user.dlt_log_handle = -1;
3099
3100 #ifdef DLT_SHM_ENABLE
3101                         /* free shared memory */
3102                         dlt_shm_free_client(&dlt_user.dlt_shm);
3103 #endif
3104
3105             if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
3106             {
3107                 dlt_user_print_msg(&msg, log);
3108             }
3109
3110             return DLT_RETURN_PIPE_ERROR;
3111         }
3112         case DLT_RETURN_ERROR:
3113         {
3114             /* other error condition */
3115             return DLT_RETURN_ERROR;
3116         }
3117                 case DLT_RETURN_OK:
3118         {
3119                 return DLT_RETURN_OK;
3120         }
3121                 default:
3122                 {
3123                         /* This case should never occur. */
3124                         return DLT_RETURN_ERROR;
3125                 }
3126         }
3127     }
3128
3129     return DLT_RETURN_OK;
3130 }
3131
3132 int dlt_user_log_send_register_application(void)
3133 {
3134     DltUserHeader userheader;
3135     DltUserControlMsgRegisterApplication usercontext;
3136
3137     DltReturnValue ret;
3138
3139     if (dlt_user.appID[0]=='\0')
3140     {
3141         return -1;
3142     }
3143
3144     /* set userheader */
3145     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION)==-1)
3146     {
3147                 return -1;
3148     }
3149
3150     /* set usercontext */
3151     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3152     usercontext.pid = getpid();
3153
3154     if (dlt_user.application_description!=0)
3155     {
3156         usercontext.description_length = strlen(dlt_user.application_description);
3157     }
3158     else
3159     {
3160         usercontext.description_length = 0;
3161     }
3162
3163     if (dlt_user.dlt_is_file)
3164     {
3165         return 0;
3166     }
3167
3168     /* log to FIFO */
3169     ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication),dlt_user.application_description,usercontext.description_length);
3170
3171     /* store message in ringbuffer, if an error has occured */
3172     if (ret!=DLT_RETURN_OK)
3173     {
3174         DLT_SEM_LOCK();
3175
3176         if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3177                             (unsigned char *)&(userheader), sizeof(DltUserHeader),
3178                             (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterApplication),
3179                             (const unsigned char*)dlt_user.application_description, usercontext.description_length)==-1)
3180              {
3181                     dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3182                     DLT_SEM_FREE();
3183                     return -1;
3184              }
3185
3186         DLT_SEM_FREE();
3187
3188         if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3189         {
3190             ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_application: Failed to queue resending.\n");
3191         }
3192     }
3193
3194     return 0;
3195 }
3196
3197 int dlt_user_log_send_unregister_application(void)
3198 {
3199     DltUserHeader userheader;
3200     DltUserControlMsgUnregisterApplication usercontext;
3201
3202     DltReturnValue ret;
3203
3204     if (dlt_user.appID[0]=='\0')
3205     {
3206         return -1;
3207     }
3208
3209     /* set userheader */
3210     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION)==-1)
3211     {
3212         return -1;
3213     }
3214
3215     /* set usercontext */
3216     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3217     usercontext.pid = getpid();
3218
3219     if (dlt_user.dlt_is_file)
3220     {
3221         return 0;
3222     }
3223
3224     /* log to FIFO */
3225     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication));
3226     return ((ret==DLT_RETURN_OK)?0:-1);
3227 }
3228
3229 int dlt_user_log_send_register_context(DltContextData *log)
3230 {
3231     DltUserHeader userheader;
3232     DltUserControlMsgRegisterContext usercontext;
3233     DltReturnValue ret;
3234
3235     if (log==0)
3236     {
3237                 return -1;
3238     }
3239
3240     if (log->handle==0)
3241     {
3242         return -1;
3243     }
3244
3245     if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3246     {
3247         return -1;
3248     }
3249
3250     /* set userheader */
3251     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT)==-1)
3252     {
3253                 return -1;
3254     }
3255
3256     /* set usercontext */
3257     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3258     dlt_set_id(usercontext.ctid,log->handle->contextID);       /* context id */
3259     usercontext.log_level_pos = log->handle->log_level_pos;
3260     usercontext.pid = getpid();
3261
3262     usercontext.log_level = (int8_t)log->log_level;
3263     usercontext.trace_status = (int8_t)log->trace_status;
3264
3265     if (log->context_description!=0)
3266     {
3267         usercontext.description_length = strlen(log->context_description);
3268     }
3269     else
3270     {
3271                 usercontext.description_length = 0;
3272     }
3273
3274     if (dlt_user.dlt_is_file)
3275     {
3276         return 0;
3277     }
3278
3279     /* log to FIFO */
3280     ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext),log->context_description,usercontext.description_length);
3281
3282     /* store message in ringbuffer, if an error has occured */
3283     if (ret!=DLT_RETURN_OK)
3284     {
3285         DLT_SEM_LOCK();
3286
3287         if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3288                             (unsigned char *)&(userheader), sizeof(DltUserHeader),
3289                             (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterContext),
3290                             (const unsigned char*)log->context_description, usercontext.description_length)==-1)
3291              {
3292                     dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3293                     DLT_SEM_FREE();
3294                     return -1;
3295              }
3296
3297         DLT_SEM_FREE();
3298
3299         if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3300         {
3301             ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_context: Failed to queue resending.\n");
3302         }
3303     }
3304
3305     return 0;
3306
3307 }
3308
3309 int dlt_user_log_send_unregister_context(DltContextData *log)
3310 {
3311     DltUserHeader userheader;
3312     DltUserControlMsgUnregisterContext usercontext;
3313     DltReturnValue ret;
3314
3315     if (log==0)
3316     {
3317         return -1;
3318     }
3319
3320     if (log->handle==0)
3321     {
3322         return -1;
3323     }
3324
3325     if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3326     {
3327         return -1;
3328     }
3329
3330     /* set userheader */
3331     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT)==-1)
3332     {
3333                 return -1;
3334     }
3335
3336     /* set usercontext */
3337     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3338     dlt_set_id(usercontext.ctid,log->handle->contextID);       /* context id */
3339     usercontext.pid = getpid();
3340
3341     if (dlt_user.dlt_is_file)
3342     {
3343         return 0;
3344     }
3345
3346     /* log to FIFO */
3347     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext));
3348         return ((ret==DLT_RETURN_OK)?0:-1);
3349 }
3350
3351 int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
3352 {
3353     DltUserHeader userheader;
3354     DltUserControlMsgAppLogLevelTraceStatus usercontext;
3355         DltReturnValue ret;
3356
3357     if ((appid==0) || (appid[0]=='\0'))
3358     {
3359         return -1;
3360     }
3361
3362     /* Removed because of DltLogLevelType and DltTraceStatusType
3363
3364     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
3365     {
3366         return -1;
3367     }
3368
3369     if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
3370     {
3371         return -1;
3372     }
3373
3374     */
3375
3376     /* set userheader */
3377     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS)==-1)
3378     {
3379                 return -1;
3380     }
3381
3382     /* set usercontext */
3383     dlt_set_id(usercontext.apid,appid);       /* application id */
3384     usercontext.log_level = loglevel;
3385     usercontext.trace_status = tracestatus;
3386
3387     if (dlt_user.dlt_is_file)
3388     {
3389         return 0;
3390     }
3391
3392     /* log to FIFO */
3393     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus));
3394     return ((ret==DLT_RETURN_OK)?0:-1);
3395 }
3396
3397 int dlt_user_log_send_log_mode(DltUserLogMode mode)
3398 {
3399     DltUserHeader userheader;
3400     DltUserControlMsgLogMode logmode;
3401
3402     DltReturnValue ret;
3403
3404     /* set userheader */
3405     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE)==-1)
3406     {
3407         return -1;
3408     }
3409
3410     /* set data */
3411     logmode.log_mode = (unsigned char) mode;
3412
3413     if (dlt_user.dlt_is_file)
3414     {
3415         return 0;
3416     }
3417
3418     /* log to FIFO */
3419     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode));
3420     return ((ret==DLT_RETURN_OK)?0:-1);
3421 }
3422
3423 int dlt_user_print_msg(DltMessage *msg, DltContextData *log)
3424 {
3425     uint8_t *databuffer_tmp;
3426     int32_t datasize_tmp;
3427     int32_t databuffersize_tmp;
3428     static char text[DLT_USER_TEXT_LENGTH];
3429
3430     if ((msg==0) || (log==0))
3431     {
3432         return -1;
3433     }
3434
3435     /* Save variables before print */
3436     databuffer_tmp = msg->databuffer;
3437     datasize_tmp = msg->datasize;
3438     databuffersize_tmp = msg->databuffersize;
3439
3440     /* Act like a receiver, convert header back to host format */
3441     msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len);
3442     dlt_message_get_extraparameters(msg,0);
3443
3444     msg->databuffer = log->buffer;
3445     msg->datasize = log->size;
3446     msg->databuffersize = log->size;
3447
3448     /* Print message as ASCII */
3449     if (dlt_message_print_ascii(msg,text,DLT_USER_TEXT_LENGTH,0)==-1)
3450     {
3451                 return -1;
3452     }
3453
3454     /* Restore variables and set len to BE*/
3455     msg->databuffer = databuffer_tmp;
3456     msg->databuffersize = databuffersize_tmp;
3457     msg->datasize =  datasize_tmp;
3458
3459     msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
3460
3461     return 0;
3462 }
3463
3464 int dlt_user_log_check_user_message(void)
3465 {
3466     int offset=0;
3467     int leave_while=0;
3468
3469     uint32_t i;
3470
3471     DltUserHeader *userheader;
3472     DltReceiver *receiver = &(dlt_user.receiver);
3473
3474     DltUserControlMsgLogLevel *usercontextll;
3475     DltUserControlMsgInjection *usercontextinj;
3476     DltUserControlMsgLogState *userlogstate;
3477     unsigned char *userbuffer;
3478
3479     /* For delayed calling of injection callback, to avoid deadlock */
3480     DltUserInjectionCallback    delayed_injection_callback;
3481     unsigned char                               *delayed_inject_buffer = 0;
3482     uint32_t                                    delayed_inject_data_length = 0;
3483
3484     /* Ensure that callback is null before searching for it */
3485     delayed_injection_callback.injection_callback = 0;
3486     delayed_injection_callback.service_id = 0;
3487
3488     if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
3489     {
3490         while (1)
3491         {
3492             if (dlt_receiver_receive_fd(receiver)<=0)
3493             {
3494                 /* No new message available */
3495                 return 0;
3496             }
3497
3498             /* look through buffer as long as data is in there */
3499             while (1)
3500             {
3501                 if (receiver->bytesRcvd < (int32_t)sizeof(DltUserHeader))
3502                 {
3503                     break;
3504                 }
3505
3506                 /* resync if necessary */
3507                 offset=0;
3508                 do
3509                 {
3510                     userheader = (DltUserHeader*) (receiver->buf+offset);
3511
3512                     /* Check for user header pattern */
3513                     if (dlt_user_check_userheader(userheader))
3514                     {
3515                         break;
3516                     }
3517                     offset++;
3518
3519                 }
3520                 while ((int32_t)(sizeof(DltUserHeader)+offset)<=receiver->bytesRcvd);
3521
3522                 /* Check for user header pattern */
3523                 if (dlt_user_check_userheader(userheader)<0 ||
3524                     dlt_user_check_userheader(userheader)==0)
3525                 {
3526                     break;
3527                 }
3528
3529                 /* Set new start offset */
3530                 if (offset>0)
3531                 {
3532                     receiver->buf+=offset;
3533                     receiver->bytesRcvd-=offset;
3534                 }
3535
3536                 switch (userheader->message)
3537                 {
3538                 case DLT_USER_MESSAGE_LOG_LEVEL:
3539                 {
3540                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel)))
3541                     {
3542                         leave_while=1;
3543                         break;
3544                     }
3545
3546                     usercontextll = (DltUserControlMsgLogLevel*) (receiver->buf+sizeof(DltUserHeader));
3547
3548                     /* Update log level and trace status */
3549                     if (usercontextll!=0)
3550                     {
3551                         DLT_SEM_LOCK();
3552
3553                         if ((usercontextll->log_level_pos >= 0) && (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries))
3554                         {
3555                             // printf("Store ll, ts\n");
3556                             if (dlt_user.dlt_ll_ts)
3557                             {
3558                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = usercontextll->log_level;
3559                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status = usercontextll->trace_status;
3560                                 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr)
3561                                         *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) = usercontextll->log_level;
3562                                 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr)
3563                                         *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) = usercontextll->trace_status;
3564                             }
3565                         }
3566
3567                         DLT_SEM_FREE();
3568                     }
3569
3570                     /* keep not read data in buffer */
3571                     if (dlt_receiver_remove(receiver,sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel))==-1)
3572                     {
3573                         return -1;
3574                     }
3575                 }
3576                 break;
3577                 case DLT_USER_MESSAGE_INJECTION:
3578                 {
3579                     /* At least, user header, user context, and service id and data_length of injected message is available */
3580                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)))
3581                     {
3582                         leave_while = 1;
3583                         break;
3584                     }
3585
3586                     usercontextinj = (DltUserControlMsgInjection*) (receiver->buf+sizeof(DltUserHeader));
3587                     userbuffer = (unsigned char*) (receiver->buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection));
3588
3589                     if (userbuffer!=0)
3590                     {
3591
3592                         if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))
3593                         {
3594                             leave_while = 1;
3595                             break;
3596                         }
3597
3598                         DLT_SEM_LOCK();
3599
3600                         if ((usercontextinj->data_length_inject>0) && (dlt_user.dlt_ll_ts))
3601                         {
3602                             /* Check if injection callback is registered for this context */
3603                             for (i=0; i<dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks;i++)
3604                             {
3605                                 if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) &&
3606                                         (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id == usercontextinj->service_id))
3607                                 {
3608                                         /* Prepare delayed injection callback call */
3609                                                                         if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback!=0)
3610                                                                         {
3611                                                                                 delayed_injection_callback.injection_callback = dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback;
3612                                                                                 delayed_injection_callback.service_id = usercontextinj->service_id;
3613                                                                                 delayed_inject_data_length = usercontextinj->data_length_inject;
3614                                                                                 delayed_inject_buffer = malloc(delayed_inject_data_length);
3615                                                                                 if(delayed_inject_buffer != 0) {
3616                                                                                         memcpy(delayed_inject_buffer, userbuffer, delayed_inject_data_length);
3617                                                                                 }
3618
3619                                                                         }
3620                                     break;
3621                                 }
3622                             }
3623                         }
3624
3625                         DLT_SEM_FREE();
3626
3627                         /* Delayed injection callback call */
3628                         if(delayed_inject_buffer != 0 && delayed_injection_callback.injection_callback != 0) {
3629                                 delayed_injection_callback.injection_callback(delayed_injection_callback.service_id, delayed_inject_buffer, delayed_inject_data_length);
3630                                 delayed_injection_callback.injection_callback = 0;
3631                                 free(delayed_inject_buffer);
3632                                 delayed_inject_buffer = NULL;
3633
3634                         }
3635
3636                         /* keep not read data in buffer */
3637                         if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))==-1)
3638                                                 {
3639                                                         return -1;
3640                                                 }
3641                     }
3642                 }
3643                 break;
3644                 case DLT_USER_MESSAGE_LOG_STATE:
3645                 {
3646                     /* At least, user header, user context, and service id and data_length of injected message is available */
3647                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))
3648                     {
3649                         leave_while = 1;
3650                         break;
3651                     }
3652
3653                     userlogstate = (DltUserControlMsgLogState*) (receiver->buf+sizeof(DltUserHeader));
3654                                         dlt_user.log_state = userlogstate->log_state;
3655
3656                                         /* keep not read data in buffer */
3657                                         if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))==-1)
3658                                         {
3659                                                 return -1;
3660                                         }
3661                 }
3662                 break;
3663                 default:
3664                 {
3665                     dlt_log(LOG_ERR,"Invalid user message type received!\n");
3666                     /* Ignore result */
3667                     dlt_receiver_remove(receiver,sizeof(DltUserHeader));
3668                                         /* In next invocation of while loop, a resync will be triggered if additional data was received */
3669                 }
3670                 break;
3671                 } /* switch() */
3672
3673                 if (leave_while==1)
3674                 {
3675                     leave_while=0;
3676                     break;
3677                 }
3678
3679             } /* while buffer*/
3680
3681             if (dlt_receiver_move_to_begin(receiver)==-1)
3682             {
3683                                 return -1;
3684             }
3685         } /* while receive */
3686     } /* if */
3687
3688     return DLT_RETURN_OK;
3689 }
3690
3691 int dlt_user_log_resend_buffer(void)
3692 {
3693         int num,count;
3694     int size;
3695         DltReturnValue ret;
3696         
3697         /* Send content of ringbuffer */
3698         DLT_SEM_LOCK();
3699         count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
3700         DLT_SEM_FREE();
3701
3702         for (num=0;num<count;num++)
3703         {
3704
3705                 DLT_SEM_LOCK();
3706                 size = dlt_buffer_copy(&(dlt_user.startup_buffer),dlt_user.resend_buffer,sizeof(dlt_user.resend_buffer));
3707
3708                 if (size>0)
3709                 {
3710 #ifdef DLT_SHM_ENABLE                                           
3711                         dlt_shm_push(&dlt_user.dlt_shm,dlt_user.resend_buffer+sizeof(DltUserHeader),size-sizeof(DltUserHeader),0,0,0,0);
3712
3713                         /* log to FIFO */
3714                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,sizeof(DltUserHeader),0,0,0,0);
3715 #else
3716                         /* log to FIFO */
3717                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,size,0,0,0,0);
3718 #endif
3719
3720                         /* in case of error, keep message in ringbuffer */                        
3721                         if (ret==DLT_RETURN_OK)
3722                         {
3723                                 dlt_buffer_remove(&(dlt_user.startup_buffer));
3724                         }
3725                         else
3726                         {
3727                                 /* keep message in ringbuffer */   
3728                                 DLT_SEM_FREE();
3729                                 return -1;
3730                         }
3731                 }
3732                 DLT_SEM_FREE();
3733         }
3734         
3735         return 0;
3736 }
3737
3738 void dlt_user_log_reattach_to_daemon(void)
3739 {
3740         uint32_t num,reregistered=0;
3741
3742         DltContext handle;
3743         DltContextData log_new;
3744
3745     if (dlt_user.dlt_log_handle<0)
3746     {
3747         dlt_user.dlt_log_handle=-1;
3748
3749         /* try to open pipe to dlt daemon */
3750         dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK);
3751         if (dlt_user.dlt_log_handle > 0)
3752         {
3753             if (dlt_user_log_init(&handle,&log_new)==-1)
3754             {
3755                 return;
3756             }
3757
3758 #ifdef DLT_SHM_ENABLE
3759                         /* init shared memory */
3760                         if (dlt_shm_init_client(&dlt_user.dlt_shm,DLT_SHM_KEY) < 0)
3761                         {
3762                                 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
3763                                 dlt_log(LOG_WARNING, str);
3764                                 //return 0; 
3765                         }   
3766 #endif
3767
3768             dlt_log(LOG_NOTICE, "Logging re-enabled!\n");
3769
3770             /* Re-register application */
3771             if (dlt_user_log_send_register_application()==-1)
3772             {
3773                 return;
3774             }
3775
3776             DLT_SEM_LOCK();
3777
3778             /* Re-register all stored contexts */
3779             for (num=0; num<dlt_user.dlt_ll_ts_num_entries; num++)
3780             {
3781                 /* Re-register stored context */
3782                 if ((dlt_user.appID[0]!='\0') && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID[0]!='\0'))
3783                 {
3784                     //dlt_set_id(log_new.appID, dlt_user.appID);
3785                     dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
3786                     handle.log_level_pos = num;
3787                     log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
3788
3789                     // Release the mutex for sending context registration:
3790                     // function  dlt_user_log_send_register_context() can take the mutex to write to the DLT buffer. => dead lock
3791                     DLT_SEM_FREE();
3792
3793                     log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
3794                     log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
3795
3796                     if (dlt_user_log_send_register_context(&log_new)==-1)
3797                     {
3798                         return;
3799                     }
3800
3801                     reregistered=1;
3802
3803                     // Lock again the mutex
3804                     // it is necessary in the for(;;) test, in order to have coherent dlt_user data all over the critical section.
3805                     DLT_SEM_LOCK();
3806
3807                 }
3808             }
3809
3810             DLT_SEM_FREE();
3811
3812             if (reregistered==1)
3813             {
3814                                 dlt_user_log_resend_buffer();
3815             }
3816         }
3817     }
3818 }
3819
3820 int dlt_user_log_send_overflow(void)
3821 {
3822     DltUserHeader userheader;
3823     DltUserControlMsgBufferOverflow userpayload;
3824     DltReturnValue ret;
3825
3826     /* set userheader */
3827     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW)==-1)
3828     {
3829         return -1;
3830     }
3831
3832     if (dlt_user.dlt_is_file)
3833     {
3834         return 0;
3835     }
3836
3837     /* set user message parameters */
3838     userpayload.overflow_counter = dlt_user.overflow_counter;
3839     dlt_set_id(userpayload.apid,dlt_user.appID);
3840
3841     /* log to FIFO */
3842     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader),
3843                               &(userpayload), sizeof(DltUserControlMsgBufferOverflow));
3844     return ((ret==DLT_RETURN_OK)?0:-1);
3845 }
3846
3847 int dlt_user_check_buffer(int *total_size, int *used_size)
3848 {
3849 #ifdef DLT_SHM_ENABLE
3850         *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm));
3851         *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm));
3852 #else
3853         *total_size = dlt_buffer_get_total_size(&(dlt_user.startup_buffer));
3854         *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer));
3855 #endif
3856         
3857         return 0; /* ok */
3858 }
3859
3860 #ifdef DLT_TEST_ENABLE
3861 void dlt_user_test_corrupt_user_header(int enable)
3862 {
3863     dlt_user.corrupt_user_header = enable;
3864 }
3865 void dlt_user_test_corrupt_message_size(int enable,int16_t size)
3866 {
3867     dlt_user.corrupt_message_size = enable;
3868     dlt_user.corrupt_message_size_size = size;
3869 }
3870 #endif
3871
3872