Removed check of double registration of contexts in user library, already checked...
[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     char ctid[DLT_ID_SIZE+1];
739
740     if (dlt_user_initialised==0)
741     {
742         if (dlt_init()<0)
743         {
744             return -1;
745         }
746     }
747
748     DLT_SEM_LOCK();
749
750     if (dlt_user.appID[0]=='\0')
751     {
752         dlt_log(LOG_ERR, "no application registered!\n");
753
754         DLT_SEM_FREE();
755         return -1;
756     }
757
758     DLT_SEM_FREE();
759
760     if ((contextid==0) || (contextid[0]=='\0'))
761     {
762         return -1;
763     }
764
765     if ((loglevel<DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel>DLT_LOG_VERBOSE) || (loglevel==DLT_LOG_DEFAULT))
766     {
767         return -1;
768     }
769
770     if ((tracestatus<DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus>DLT_TRACE_STATUS_ON) || (tracestatus==DLT_TRACE_STATUS_DEFAULT))
771     {
772         return -1;
773     }
774
775     if (dlt_user_log_init(handle, &log)==-1)
776     {
777         return -1;
778     }
779
780     /* Reset message counter */
781     handle->mcnt = 0;
782
783     /* Store context id in log level/trace status field */
784
785     /* Check if already registered, else register context */
786     DLT_SEM_LOCK();
787
788     /* Check of double context registration removed */
789     /* Double registration is already checked by daemon */
790
791         /* Allocate or expand context array */
792         if (dlt_user.dlt_ll_ts == 0)
793         {
794                 dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*DLT_USER_CONTEXT_ALLOC_SIZE);
795                 if (dlt_user.dlt_ll_ts==0)
796                 {
797                         DLT_SEM_FREE();
798                         return -1;
799                 }
800
801                 dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE;
802
803                 /* Initialize new entries */
804                 for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
805                 {
806                         dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
807
808                         /* At startup, logging and tracing is locally enabled */
809                         /* the correct log level/status is set after received from daemon */
810                         dlt_user.dlt_ll_ts[i].log_level    = DLT_USER_INITIAL_LOG_LEVEL;
811                         dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
812
813                         dlt_user.dlt_ll_ts[i].log_level_ptr    = 0;
814                         dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
815
816                         dlt_user.dlt_ll_ts[i].context_description = 0;
817
818                         dlt_user.dlt_ll_ts[i].injection_table = 0;
819                         dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
820                 }
821         }
822         else
823         {
824                 if ((dlt_user.dlt_ll_ts_num_entries%DLT_USER_CONTEXT_ALLOC_SIZE)==0)
825                 {
826                         /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
827                         dlt_ll_ts_type *old_ll_ts;
828                         uint32_t old_max_entries;
829
830                         old_ll_ts = dlt_user.dlt_ll_ts;
831                         old_max_entries = dlt_user.dlt_ll_ts_max_num_entries;
832
833                         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;
834                         dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*
835                                                                  dlt_user.dlt_ll_ts_max_num_entries);
836                         if (dlt_user.dlt_ll_ts==0)
837                         {
838                                 dlt_user.dlt_ll_ts = old_ll_ts;
839                                 dlt_user.dlt_ll_ts_max_num_entries = old_max_entries;
840                                 DLT_SEM_FREE();
841                                 return -1;
842                         }
843
844                         memcpy(dlt_user.dlt_ll_ts,old_ll_ts,sizeof(dlt_ll_ts_type)*dlt_user.dlt_ll_ts_num_entries);
845                         free(old_ll_ts);
846
847                         /* Initialize new entries */
848                         for (i=dlt_user.dlt_ll_ts_num_entries;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
849                         {
850                                 dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
851
852                                 /* At startup, logging and tracing is locally enabled */
853                                 /* the correct log level/status is set after received from daemon */
854                                 dlt_user.dlt_ll_ts[i].log_level    = DLT_USER_INITIAL_LOG_LEVEL;
855                                 dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
856
857                                 dlt_user.dlt_ll_ts[i].log_level_ptr    = 0;
858                                 dlt_user.dlt_ll_ts[i].trace_status_ptr = 0;
859
860                                 dlt_user.dlt_ll_ts[i].context_description = 0;
861
862                                 dlt_user.dlt_ll_ts[i].injection_table = 0;
863                                 dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
864                         }
865                 }
866         }
867
868         /* Store locally context id and context description */
869         dlt_set_id(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].contextID, contextid);
870
871         if (dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description!=0)
872         {
873                 free(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description);
874         }
875
876         dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = 0;
877
878         if (description!=0)
879         {
880                 size_t desc_len = strlen(description);
881                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = malloc(desc_len+1);
882                 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description == 0)
883                 {
884                         DLT_SEM_FREE();
885                         return -1;
886                 }
887
888                 strncpy(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description, description, desc_len);
889
890                 /* Terminate transmitted string with 0 */
891                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description[desc_len]='\0';
892         }
893
894         if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
895         {
896                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr = malloc(sizeof(int8_t));
897                 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr == 0)
898                 {
899                         DLT_SEM_FREE();
900                         return -1;
901                 }
902         }
903         if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
904         {
905                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr = malloc(sizeof(int8_t));
906                 if(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr == 0)
907                 {
908                         DLT_SEM_FREE();
909                         return -1;
910                 }
911         }
912
913         if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
914         {
915                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = loglevel;
916         }
917
918         if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
919         {
920                 dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
921         }
922
923         /* Prepare transfer struct */
924         //dlt_set_id(log->appID, dlt_user.appID);
925         dlt_set_id(handle->contextID, contextid);
926         handle->log_level_pos = dlt_user.dlt_ll_ts_num_entries;
927
928         handle->log_level_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level_ptr;
929         handle->trace_status_ptr = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status_ptr;
930
931         log.context_description = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description;
932
933         *(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;
934         *(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;
935
936         if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
937         {
938                 log.log_level = loglevel;
939         }
940         else
941         {
942                 log.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
943         }
944
945         if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
946         {
947                 log.trace_status = tracestatus;
948         }
949         else
950         {
951                 log.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
952         }
953
954         dlt_user.dlt_ll_ts_num_entries++;
955
956         DLT_SEM_FREE();
957
958         return dlt_user_log_send_register_context(&log);
959 }
960
961 int dlt_unregister_app(void)
962 {
963     int ret;
964
965     if (dlt_user_initialised==0)
966     {
967         return -1;
968     }
969
970     /* Inform daemon to unregister application and all of its contexts */
971     ret = dlt_user_log_send_unregister_application();
972
973     DLT_SEM_LOCK();
974
975     /* Clear and free local stored application information */
976     dlt_set_id(dlt_user.appID, "");
977
978     if (dlt_user.application_description!=0)
979     {
980         free(dlt_user.application_description);
981     }
982
983     dlt_user.application_description = 0;
984
985     DLT_SEM_FREE();
986
987     return ret;
988 }
989
990 int dlt_unregister_context(DltContext *handle)
991 {
992     DltContextData log;
993     int ret;
994
995     if (dlt_user_initialised==0)
996     {
997         return -1;
998     }
999
1000     if (dlt_user_log_init(handle, &log) == -1)
1001     {
1002                 return -1;
1003     }
1004
1005     DLT_SEM_LOCK();
1006
1007     handle->log_level_ptr = 0;
1008     handle->trace_status_ptr = 0;
1009
1010     if (dlt_user.dlt_ll_ts)
1011     {
1012         /* Clear and free local stored context information */
1013         dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, "");
1014
1015         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
1016         dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
1017
1018         if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description!=0)
1019         {
1020             free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
1021         }
1022
1023         if (dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr!=0)
1024         {
1025             free(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr);
1026             dlt_user.dlt_ll_ts[handle->log_level_pos].log_level_ptr = 0;
1027         }
1028
1029         if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr!=0)
1030         {
1031             free(dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr);
1032             dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status_ptr = 0;
1033         }
1034
1035         dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = 0;
1036
1037         if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table)
1038         {
1039             free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
1040             dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = 0;
1041         }
1042
1043         dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks     = 0;
1044     }
1045
1046     DLT_SEM_FREE();
1047
1048     /* Inform daemon to unregister context */
1049     ret = dlt_user_log_send_unregister_context(&log);
1050
1051     return ret;
1052 }
1053
1054 int dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus)
1055 {
1056     uint32_t i;
1057     int ret;
1058
1059     if (dlt_user_initialised==0)
1060     {
1061         if (dlt_init()<0)
1062         {
1063             return -1;
1064         }
1065     }
1066
1067     /* Removed because of DltLogLevelType and DltTraceStatusType
1068
1069     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
1070     {
1071         return -1;
1072     }
1073
1074     if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
1075     {
1076         return -1;
1077     }
1078
1079     if (dlt_user.dlt_ll_ts==0)
1080     {
1081         return -1;
1082     }
1083
1084     */
1085
1086     DLT_SEM_LOCK();
1087     if (dlt_user.dlt_ll_ts==0)
1088     {
1089         DLT_SEM_FREE();
1090         return -1;
1091     }
1092
1093     /* Update local structures */
1094     for (i=0; i<dlt_user.dlt_ll_ts_num_entries;i++)
1095     {
1096         dlt_user.dlt_ll_ts[i].log_level = loglevel;
1097         dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
1098         if(dlt_user.dlt_ll_ts[i].log_level_ptr)
1099                 *(dlt_user.dlt_ll_ts[i].log_level_ptr) = loglevel;
1100         if(dlt_user.dlt_ll_ts[i].trace_status_ptr)
1101                 *(dlt_user.dlt_ll_ts[i].trace_status_ptr) = tracestatus;
1102     }
1103
1104     DLT_SEM_FREE();
1105
1106     /* Inform DLT server about update */
1107     ret = dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus);
1108
1109     return ret;
1110 }
1111
1112 int dlt_get_log_state()
1113 {
1114         return dlt_user.log_state;
1115 }
1116
1117 int dlt_set_log_mode(DltUserLogMode mode)
1118 {
1119     if (dlt_user_initialised==0)
1120     {
1121         if (dlt_init()<0)
1122         {
1123             return -1;
1124         }
1125     }
1126
1127         return dlt_user_log_send_log_mode(mode);
1128 }
1129
1130 int dlt_forward_msg(void *msgdata,size_t size)
1131 {
1132     DltUserHeader userheader;
1133     DltReturnValue ret;
1134
1135     if ((msgdata==0) || (size==0))
1136     {
1137         return -1;
1138     }
1139
1140     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
1141     {
1142         /* Type of internal user message; same value for Trace messages */
1143         return -1;
1144     }
1145
1146     if (dlt_user.dlt_is_file)
1147     {
1148         /* log to file */
1149         ret = dlt_user_log_out2(dlt_user.dlt_log_handle, msgdata, size, 0, 0);
1150         return ((ret==DLT_RETURN_OK)?0:-1);
1151     }
1152     else
1153     {
1154         /* Reattach to daemon if neccesary */
1155         dlt_user_log_reattach_to_daemon();
1156
1157         if (dlt_user.overflow_counter)
1158         {
1159             if (dlt_user_log_send_overflow()==0)
1160             {
1161                                 sprintf(str,"Buffer full! %u messages discarded!\n",dlt_user.overflow_counter);
1162                                 dlt_log(LOG_ERR, str);
1163                 dlt_user.overflow_counter=0;            }
1164         }
1165
1166         /* log to FIFO */
1167         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
1168                                 &(userheader), sizeof(DltUserHeader),
1169                                 msgdata, size, 0, 0);
1170
1171         /* store message in ringbuffer, if an error has occured */
1172         if (ret!=DLT_RETURN_OK)
1173         {
1174             DLT_SEM_LOCK();
1175
1176             if (dlt_buffer_push3(&(dlt_user.startup_buffer),
1177                                 (unsigned char *)&(userheader), sizeof(DltUserHeader),
1178                                  msgdata, size, 0, 0)==-1)
1179                         {
1180                 if(dlt_user.overflow_counter==0)
1181                 {
1182                         dlt_log(LOG_ERR,"Buffer full! First message discarded!\n");
1183                 }
1184                 ret = DLT_RETURN_BUFFER_FULL;
1185                         }
1186
1187             DLT_SEM_FREE();
1188
1189             if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
1190             {
1191                 ;//dlt_log(LOG_WARNING, "dlt_forward_msg: Failed to queue resending.\n");
1192             }
1193         }
1194
1195         switch (ret)
1196         {
1197         case DLT_RETURN_BUFFER_FULL:
1198         {
1199                 /* Buffer full */
1200             dlt_user.overflow_counter += 1;
1201                 return -1;
1202         }
1203         case DLT_RETURN_PIPE_FULL:
1204         {
1205             /* data could not be written */
1206             return -1;
1207         }
1208         case DLT_RETURN_PIPE_ERROR:
1209         {
1210             /* handle not open or pipe error */
1211             close(dlt_user.dlt_log_handle);
1212             dlt_user.dlt_log_handle = -1;
1213
1214             return -1;
1215         }
1216         case DLT_RETURN_ERROR:
1217         {
1218             /* other error condition */
1219             return -1;
1220         }
1221         case DLT_RETURN_OK:
1222         {
1223                 return 0;
1224         }
1225                 default:
1226                 {
1227                         /* This case should not occur */
1228                         return -1;
1229                 }
1230         }
1231     }
1232
1233     return 0;
1234 }
1235
1236 /* ********************************************************************************************* */
1237
1238 inline int dlt_user_log_write_start(DltContext *handle, DltContextData *log,DltLogLevelType loglevel)
1239 {
1240     return dlt_user_log_write_start_id(handle,log,loglevel,DLT_USER_DEFAULT_MSGID);
1241 }
1242
1243 int dlt_user_log_write_start_id(DltContext *handle, DltContextData *log,DltLogLevelType loglevel, uint32_t messageid)
1244 {
1245         if(dlt_user_initialised==0)
1246         {
1247                 if (dlt_init()<0)
1248                 {
1249                         return -1;
1250                 }
1251         }
1252     if (log==0)
1253     {
1254         return -1;
1255     }
1256
1257     if (dlt_user_log_init(handle, log)==-1)
1258     {
1259                 return -1;
1260     }
1261
1262     if (dlt_user.dlt_ll_ts==0)
1263     {
1264         return -1;
1265     }
1266
1267     if (handle->log_level_ptr && (loglevel<=(int)*(handle->log_level_ptr) ) && (loglevel!=0))
1268     {
1269                 log->args_num = 0;
1270         log->log_level = loglevel;
1271
1272         /* In non-verbose mode, insert message id */
1273         if (dlt_user.verbose_mode==0)
1274         {
1275             if ((sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1276             {
1277                 return -1;
1278             }
1279             /* Write message id */
1280             memcpy(log->buffer,&(messageid),sizeof(uint32_t));
1281             log->size = sizeof(uint32_t);
1282
1283             /* as the message id is part of each message in non-verbose mode,
1284                it doesn't increment the argument counter in extended header (if used) */
1285         }
1286         else log->size=0;
1287         return 1;
1288     }
1289
1290     return -1;
1291 }
1292
1293 int dlt_user_log_write_finish(DltContextData *log)
1294 {
1295     if (log==0)
1296     {
1297         return -1;
1298     }
1299
1300     return dlt_user_log_send_log(log, DLT_TYPE_LOG) < 0 ? -1 : 0;
1301 }
1302
1303 int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length)
1304 {
1305     uint16_t arg_size;
1306     uint32_t type_info;
1307
1308     if (log==0)
1309     {
1310         return -1;
1311     }
1312
1313     if ((log->size+length+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1314     {
1315         return -1;
1316     }
1317
1318     if (dlt_user.verbose_mode)
1319     {
1320         if ((log->size+length+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1321         {
1322             return -1;
1323         }
1324
1325         /* Transmit type information */
1326         type_info = DLT_TYPE_INFO_RAWD;
1327
1328         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1329         log->size += sizeof(uint32_t);
1330
1331     }
1332
1333     /* First transmit length of raw data, then the raw data itself */
1334     arg_size = (uint16_t)length;
1335
1336     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1337     log->size += sizeof(uint16_t);
1338
1339     memcpy((log->buffer)+log->size,data,arg_size);
1340     log->size += arg_size;
1341
1342     log->args_num ++;
1343
1344     return 0;
1345 }
1346
1347 int dlt_user_log_write_float32(DltContextData *log, float32_t data)
1348 {
1349     uint32_t type_info;
1350
1351     if (log==0)
1352     {
1353         return -1;
1354     }
1355
1356     if (sizeof(float32_t)!=4)
1357     {
1358         return -1;
1359     }
1360
1361     if ((log->size+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1362     {
1363         return -1;
1364     }
1365
1366     if (dlt_user.verbose_mode)
1367     {
1368         if ((log->size+sizeof(uint32_t)+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1369         {
1370             return -1;
1371         }
1372
1373         type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
1374
1375         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1376         log->size += sizeof(uint32_t);
1377     }
1378
1379     memcpy((log->buffer)+log->size,&data, sizeof(float32_t));
1380     log->size += sizeof(float32_t);
1381
1382     log->args_num ++;
1383
1384     return 0;
1385 }
1386
1387 int dlt_user_log_write_float64(DltContextData *log, float64_t data)
1388 {
1389     uint32_t type_info;
1390
1391     if (log==0)
1392     {
1393         return -1;
1394     }
1395
1396     if (sizeof(float64_t)!=8)
1397     {
1398         return -1;
1399     }
1400
1401     if ((log->size+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1402     {
1403         return -1;
1404     }
1405
1406     if (dlt_user.verbose_mode)
1407     {
1408         if ((log->size+sizeof(uint32_t)+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1409         {
1410             return -1;
1411         }
1412
1413         type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
1414
1415         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1416         log->size += sizeof(uint32_t);
1417     }
1418
1419     memcpy((log->buffer)+log->size,&data, sizeof(float64_t));
1420     log->size += sizeof(float64_t);
1421
1422     log->args_num ++;
1423
1424     return 0;
1425 }
1426
1427 int dlt_user_log_write_uint( DltContextData *log, unsigned int data)
1428 {
1429     if (log==0)
1430     {
1431         return -1;
1432     }
1433
1434     switch (sizeof(unsigned int))
1435     {
1436     case 1:
1437     {
1438         return dlt_user_log_write_uint8(log, (uint8_t)data);
1439         break;
1440     }
1441     case 2:
1442     {
1443         return dlt_user_log_write_uint16(log, (uint16_t)data);
1444         break;
1445     }
1446     case 4:
1447     {
1448         return dlt_user_log_write_uint32(log, (uint32_t)data);
1449         break;
1450     }
1451     case 8:
1452     {
1453         return dlt_user_log_write_uint64(log, (uint64_t)data);
1454                 break;
1455     }
1456     default:
1457     {
1458         return -1;
1459         break;
1460     }
1461     }
1462
1463     return 0;
1464 }
1465
1466 int dlt_user_log_write_uint8(DltContextData *log, uint8_t data)
1467 {
1468     uint32_t type_info;
1469
1470     if (log==0)
1471     {
1472         return -1;
1473     }
1474
1475     if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1476     {
1477         return -1;
1478     }
1479
1480     if (dlt_user.verbose_mode)
1481     {
1482         if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1483         {
1484             return -1;
1485         }
1486
1487         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
1488
1489         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1490         log->size += sizeof(uint32_t);
1491     }
1492
1493     memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1494     log->size += sizeof(uint8_t);
1495
1496     log->args_num ++;
1497
1498     return 0;
1499 }
1500
1501 int dlt_user_log_write_uint16(DltContextData *log, uint16_t data)
1502 {
1503     uint32_t type_info;
1504
1505     if (log==0)
1506     {
1507         return -1;
1508     }
1509
1510     if ((log->size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1511     {
1512         return -1;
1513     }
1514
1515     if (dlt_user.verbose_mode)
1516     {
1517         if ((log->size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1518         {
1519             return -1;
1520         }
1521
1522         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
1523
1524         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1525         log->size += sizeof(uint32_t);
1526     }
1527
1528     memcpy((log->buffer)+log->size,&data,sizeof(uint16_t));
1529     log->size += sizeof(uint16_t);
1530
1531     log->args_num ++;
1532
1533     return 0;
1534 }
1535
1536 int dlt_user_log_write_uint32(DltContextData *log, uint32_t data)
1537 {
1538     uint32_t type_info;
1539
1540     if (log==0)
1541     {
1542         return -1;
1543     }
1544
1545     if ((log->size+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1546     {
1547         return -1;
1548     }
1549
1550     if (dlt_user.verbose_mode)
1551     {
1552         if ((log->size+sizeof(uint32_t)+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1553         {
1554             return -1;
1555         }
1556
1557         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
1558
1559         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1560         log->size += sizeof(uint32_t);
1561     }
1562
1563     memcpy((log->buffer)+log->size,&data, sizeof(uint32_t));
1564     log->size += sizeof(uint32_t);
1565
1566     log->args_num ++;
1567
1568     return 0;
1569 }
1570
1571 int dlt_user_log_write_uint64(DltContextData *log, uint64_t data)
1572 {
1573     uint32_t type_info;
1574
1575     if (log==0)
1576     {
1577         return -1;
1578     }
1579
1580     if ((log->size+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1581     {
1582         return -1;
1583     }
1584
1585     if (dlt_user.verbose_mode)
1586     {
1587         if ((log->size+sizeof(uint32_t)+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1588         {
1589             return -1;
1590         }
1591
1592         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
1593
1594         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1595         log->size +=sizeof(uint32_t);
1596     }
1597
1598     memcpy((log->buffer)+log->size,&data,sizeof(uint64_t));
1599     log->size += sizeof(uint64_t);
1600
1601     log->args_num ++;
1602
1603     return 0;
1604 }
1605
1606 int dlt_user_log_write_int(DltContextData *log, int data)
1607 {
1608     if (log==0)
1609     {
1610         return -1;
1611     }
1612
1613     switch (sizeof(int))
1614     {
1615     case 1:
1616     {
1617         return dlt_user_log_write_int8(log, (int8_t)data);
1618         break;
1619     }
1620     case 2:
1621     {
1622         return dlt_user_log_write_int16(log, (int16_t)data);
1623         break;
1624     }
1625     case 4:
1626     {
1627         return dlt_user_log_write_int32(log, (int32_t)data);
1628         break;
1629     }
1630     case 8:
1631     {
1632         return dlt_user_log_write_int64(log, (int64_t)data);
1633                 break;
1634     }
1635     default:
1636     {
1637         return -1;
1638         break;
1639     }
1640     }
1641
1642     return 0;
1643 }
1644
1645 int dlt_user_log_write_int8(DltContextData *log, int8_t data)
1646 {
1647     uint32_t type_info;
1648
1649     if (log==0)
1650     {
1651         return -1;
1652     }
1653
1654     if ((log->size+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1655     {
1656         return -1;
1657     }
1658
1659     if (dlt_user.verbose_mode)
1660     {
1661         if ((log->size+sizeof(uint32_t)+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1662         {
1663             return -1;
1664         }
1665
1666         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
1667
1668         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1669         log->size += sizeof(uint32_t);
1670     }
1671
1672     memcpy((log->buffer)+log->size,&data,sizeof(int8_t));
1673     log->size += sizeof(int8_t);
1674
1675     log->args_num ++;
1676
1677     return 0;
1678 }
1679
1680 int dlt_user_log_write_int16(DltContextData *log, int16_t data)
1681 {
1682     uint32_t type_info;
1683
1684     if (log==0)
1685     {
1686         return -1;
1687     }
1688
1689     if ((log->size+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1690     {
1691         return -1;
1692     }
1693
1694     if (dlt_user.verbose_mode)
1695     {
1696         if ((log->size+sizeof(uint32_t)+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1697                 {
1698             return -1;
1699                 }
1700
1701         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
1702
1703         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1704         log->size += sizeof(uint32_t);
1705     }
1706
1707     memcpy((log->buffer)+log->size,&data,sizeof(int16_t));
1708     log->size += sizeof(int16_t);
1709
1710     log->args_num ++;
1711
1712     return 0;
1713 }
1714
1715 int dlt_user_log_write_int32(DltContextData *log, int32_t data)
1716 {
1717     uint32_t type_info;
1718
1719     if (log==0)
1720     {
1721         return -1;
1722     }
1723
1724     if ((log->size+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1725     {
1726         return -1;
1727     }
1728
1729     if (dlt_user.verbose_mode)
1730     {
1731         if ((log->size+sizeof(uint32_t)+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1732         {
1733             return -1;
1734         }
1735
1736         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
1737
1738         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1739         log->size += sizeof(uint32_t);
1740     }
1741
1742     memcpy((log->buffer)+log->size,&data, sizeof(int32_t));
1743     log->size += sizeof(int32_t);
1744
1745     log->args_num ++;
1746
1747     return 0;
1748 }
1749
1750 int dlt_user_log_write_int64(DltContextData *log, int64_t data)
1751 {
1752     uint32_t type_info;
1753
1754     if (log==0)
1755     {
1756         return -1;
1757     }
1758
1759     if ((log->size+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1760     {
1761         return -1;
1762     }
1763
1764     if (dlt_user.verbose_mode)
1765     {
1766         if ((log->size+sizeof(uint32_t)+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1767         {
1768             return -1;
1769         }
1770
1771         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
1772
1773         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1774         log->size += sizeof(uint32_t);
1775     }
1776
1777     memcpy((log->buffer)+log->size,&data,sizeof(int64_t));
1778     log->size += sizeof(int64_t);
1779
1780     log->args_num ++;
1781
1782     return 0;
1783 }
1784
1785 int dlt_user_log_write_bool(DltContextData *log, uint8_t data)
1786 {
1787     uint32_t type_info;
1788
1789     if (log==0)
1790     {
1791         return -1;
1792     }
1793
1794     if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1795     {
1796         return -1;
1797     }
1798
1799     if (dlt_user.verbose_mode)
1800     {
1801         if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1802         {
1803             return -1;
1804         }
1805
1806         type_info = DLT_TYPE_INFO_BOOL;
1807
1808         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1809         log->size += sizeof(uint32_t);
1810     }
1811
1812     memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1813     log->size += sizeof(uint8_t);
1814
1815     log->args_num ++;
1816
1817     return 0;
1818 }
1819
1820 int dlt_user_log_write_string(DltContextData *log, const char *text)
1821 {
1822     uint16_t arg_size;
1823     uint32_t type_info;
1824
1825     if ((log==0) || (text==0))
1826     {
1827         return -1;
1828     }
1829
1830     if ((log->size+(strlen(text)+1)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1831     {
1832         return -1;
1833     }
1834
1835     if (dlt_user.verbose_mode)
1836     {
1837         if ((log->size+(strlen(text)+1)+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1838         {
1839             return -1;
1840         }
1841
1842         type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_ASCII;
1843
1844         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1845         log->size += sizeof(uint32_t);
1846     }
1847
1848     arg_size = strlen(text) + 1;
1849
1850     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1851     log->size += sizeof(uint16_t);
1852
1853     memcpy((log->buffer)+log->size,text,arg_size);
1854     log->size += arg_size;
1855
1856     log->args_num ++;
1857
1858     return 0;
1859 }
1860
1861 int dlt_user_log_write_utf8_string(DltContextData *log, const char *text)
1862 {
1863     uint16_t arg_size;
1864     uint32_t type_info;
1865
1866     if ((log==0) || (text==0))
1867     {
1868         return -1;
1869     }
1870
1871     arg_size = strlen(text)+1;
1872
1873     if ((log->size+arg_size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1874     {
1875         return -1;
1876     }
1877
1878     if (dlt_user.verbose_mode)
1879     {
1880         if ((log->size+arg_size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1881         {
1882             return -1;
1883         }
1884
1885         type_info = DLT_TYPE_INFO_STRG | DLT_SCOD_UTF8;
1886
1887         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1888         log->size += sizeof(uint32_t);
1889     }
1890
1891     arg_size = strlen(text) + 1;
1892
1893     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1894     log->size += sizeof(uint16_t);
1895
1896     memcpy((log->buffer)+log->size,text,arg_size);
1897     log->size += arg_size;
1898
1899     log->args_num ++;
1900
1901     return 0;
1902 }
1903
1904 int dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
1905                                     int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length))
1906 {
1907     DltContextData log;
1908     uint32_t i,j,k;
1909     int found = 0;
1910
1911         DltUserInjectionCallback *old;
1912
1913     if (handle==0)
1914     {
1915         return -1;
1916     }
1917
1918     if (dlt_user_log_init(handle, &log)==-1)
1919     {
1920                 return -1;
1921     }
1922
1923     if (service_id<DLT_USER_INJECTION_MIN)
1924     {
1925         return -1;
1926     }
1927     /* This function doesn't make sense storing to local file is choosen;
1928        so terminate this function */
1929     if (dlt_user.dlt_is_file)
1930     {
1931         return 0;
1932     }
1933
1934     DLT_SEM_LOCK();
1935
1936     if (dlt_user.dlt_ll_ts==0)
1937     {
1938         DLT_SEM_FREE();
1939         return 0;
1940     }
1941
1942     /* Insert callback in corresponding table */
1943     i=handle->log_level_pos;
1944
1945     /* Insert each service_id only once */
1946     for (k=0;k<dlt_user.dlt_ll_ts[i].nrcallbacks;k++)
1947     {
1948         if ((dlt_user.dlt_ll_ts[i].injection_table) &&
1949                 (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id))
1950         {
1951             found = 1;
1952             break;
1953         }
1954     }
1955
1956     if (found)
1957     {
1958         j = k;
1959     }
1960     else
1961     {
1962         j=dlt_user.dlt_ll_ts[i].nrcallbacks;
1963
1964         /* Allocate or expand injection table */
1965         if (dlt_user.dlt_ll_ts[i].injection_table == 0)
1966         {
1967             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback));
1968             if(dlt_user.dlt_ll_ts[i].injection_table == 0)
1969             {
1970                 DLT_SEM_FREE();
1971                 return -1;
1972             }
1973         }
1974         else
1975         {
1976             old = dlt_user.dlt_ll_ts[i].injection_table;
1977             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback)*(j+1));
1978             if(dlt_user.dlt_ll_ts[i].injection_table == 0)
1979             {
1980                 dlt_user.dlt_ll_ts[i].injection_table = old;
1981                 DLT_SEM_FREE();
1982                 return -1;
1983             }
1984             memcpy(dlt_user.dlt_ll_ts[i].injection_table,old,sizeof(DltUserInjectionCallback)*j);
1985             free(old);
1986         }
1987
1988         dlt_user.dlt_ll_ts[i].nrcallbacks++;
1989     }
1990
1991     /* Store service_id and corresponding function pointer for callback function */
1992     dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id;
1993     dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = dlt_injection_callback;
1994
1995     DLT_SEM_FREE();
1996     return 0;
1997 }
1998
1999 /**
2000  * NW Trace related
2001  */
2002
2003
2004 int check_buffer()
2005 {
2006         int total_size, used_size;
2007         dlt_user_check_buffer(&total_size, &used_size);
2008
2009         if((total_size - used_size) < (total_size/2))
2010         {
2011                 return -1;
2012         }
2013         return 1;
2014 }
2015
2016 /**
2017  * Send the start of a segment chain.
2018  * Returns -1 on failure
2019  */
2020 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)
2021 {
2022
2023     DltContextData log;
2024         struct timeval tv;
2025
2026     if (handle==NULL)
2027     {
2028         return -1;
2029     }
2030
2031     if (dlt_user_log_init(handle, &log)==-1)
2032     {
2033                 return -1;
2034     }
2035
2036
2037     if (dlt_user.dlt_ll_ts==0)
2038     {
2039         return -1;
2040     }
2041
2042     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2043     {
2044
2045         log.args_num = 0;
2046         log.trace_status = nw_trace_type;
2047         log.size = 0;
2048
2049         gettimeofday(&tv, NULL);
2050         *id = tv.tv_usec;
2051
2052         /* Write identifier */
2053         if(dlt_user_log_write_string(&log, "NWST") < 0)
2054         {
2055                 return -1;
2056         }
2057
2058         /* Write stream handle */
2059         if(dlt_user_log_write_uint16(&log, *id) < 0)
2060         {
2061                 return -1;
2062         }
2063
2064         /* Write header */
2065         if(dlt_user_log_write_raw(&log, header, header_len) < 0)
2066         {
2067                 return -1;
2068         }
2069
2070         /* Write size of payload */
2071         if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2072         {
2073                 return -1;
2074         }
2075
2076         /* Write expected segment count */
2077         uint16_t segment_count = payload_len/DLT_MAX_TRACE_SEGMENT_SIZE+1;
2078
2079         /* If segments align perfectly with segment size, avoid sending empty segment */
2080         if((payload_len % DLT_MAX_TRACE_SEGMENT_SIZE) == 0)
2081         {
2082                 segment_count--;
2083         }
2084
2085         if(dlt_user_log_write_uint16(&log, segment_count) < 0)
2086         {
2087                 return -1;
2088         }
2089
2090         /* Write length of one segment */
2091         if(dlt_user_log_write_uint16(&log, DLT_MAX_TRACE_SEGMENT_SIZE) < 0)
2092         {
2093                 return -1;
2094         }
2095
2096         /* Send log */
2097         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2098     }
2099     return 0;
2100 }
2101
2102 int dlt_user_trace_network_segmented_segment(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type, int sequence, uint16_t payload_len, void *payload)
2103 {
2104         while(check_buffer() < 0)
2105         {
2106                 usleep(1000*50); // Wait 50ms
2107                 dlt_user_log_resend_buffer();
2108         }
2109
2110     if (handle==NULL)
2111     {
2112         return -1;
2113     }
2114
2115     DltContextData log;
2116
2117     if (dlt_user_log_init(handle, &log)==-1)
2118     {
2119                 return -1;
2120     }
2121
2122     if (dlt_user.dlt_ll_ts==0)
2123     {
2124         return -1;
2125     }
2126
2127     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2128     {
2129
2130         log.args_num = 0;
2131         log.trace_status = nw_trace_type;
2132         log.size = 0;
2133
2134         /* Write identifier */
2135         if(dlt_user_log_write_string(&log, "NWCH") < 0)
2136         {
2137                 return -1;
2138         }
2139
2140         /* Write stream handle */
2141         if(dlt_user_log_write_uint16(&log, id) < 0)
2142         {
2143                 return -1;
2144         }
2145
2146         /* Write segment sequence number */
2147         if(dlt_user_log_write_uint16(&log, sequence) < 0)
2148         {
2149                 return -1;
2150         }
2151
2152         /* Write data */
2153         if(dlt_user_log_write_raw(&log, payload, payload_len) < 0)
2154         {
2155                 return -1;
2156         }
2157
2158         /* Send log */
2159         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2160     }
2161
2162     /* Allow other threads to log between chunks */
2163         pthread_yield();
2164     return 0;
2165 }
2166
2167 int dlt_user_trace_network_segmented_end(uint16_t id, DltContext *handle, DltNetworkTraceType nw_trace_type)
2168 {
2169     DltContextData log;
2170
2171     if (handle==0)
2172     {
2173         return -1;
2174     }
2175
2176     if (dlt_user_log_init(handle, &log)==-1)
2177     {
2178                 return -1;
2179     }
2180
2181
2182
2183     if (dlt_user.dlt_ll_ts==0)
2184     {
2185         return -1;
2186     }
2187
2188     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2189     {
2190
2191         log.args_num = 0;
2192         log.trace_status = nw_trace_type;
2193         log.size = 0;
2194
2195         /* Write identifier */
2196         if(dlt_user_log_write_string(&log, "NWEN") < 0)
2197         {
2198                 return -1;
2199         }
2200
2201         /* Write stream handle */
2202         if(dlt_user_log_write_uint(&log, id) < 0)
2203         {
2204                 return -1;
2205         }
2206
2207         /* Send log */
2208         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2209     }
2210     return 0;
2211 }
2212
2213
2214 void dlt_user_trace_network_segmented_thread(void *unused)
2215 {
2216         /* Unused on purpose. */
2217         (void) unused;
2218
2219     prctl(PR_SET_NAME, "dlt_segmented", 0, 0, 0);
2220
2221         s_segmented_data *data;
2222
2223         while(1)
2224         {
2225                 // Wait until message queue is initialized
2226                 pthread_mutex_lock(&mq_mutex);
2227                 if(dlt_user.dlt_segmented_queue_read_handle < 0)
2228                 {
2229                         pthread_cond_wait(&mq_init_condition, &mq_mutex);
2230                 }
2231                 pthread_mutex_unlock(&mq_mutex);
2232
2233                 ssize_t read = mq_receive(dlt_user.dlt_segmented_queue_read_handle, (char *)&data,
2234                                         sizeof(s_segmented_data * ), NULL);
2235
2236                 if(read != sizeof(s_segmented_data *))
2237                 {
2238
2239                         char str[255];
2240                         snprintf(str,254,"NWTSegmented: Error while reading queue: %s \n",strerror(errno));
2241                         dlt_log(LOG_CRIT, str);
2242                         continue;
2243                 }
2244
2245                 /* Indicator just to try to flush the buffer */
2246                 if(data->payload_len == DLT_DELAYED_RESEND_INDICATOR_PATTERN)
2247                 {
2248                         // Sleep 100ms, to allow other process to read FIFO
2249                         usleep(100*1000);
2250                         if(dlt_user_log_resend_buffer() < 0)
2251                         {
2252                                 // Requeue if still not empty
2253                                 if ( dlt_user_queue_resend() < 0 )
2254                                 {
2255                                     //dlt_log(LOG_WARNING, "Failed to queue resending in dlt_user_trace_network_segmented_thread.\n");
2256                                 }
2257                         }
2258                         free(data);
2259                         continue;
2260                 }
2261
2262                 dlt_user_trace_network_segmented_thread_segmenter(data);
2263
2264                 /* Send the end message */
2265                 DltReturnValue err = dlt_user_trace_network_segmented_end(data->id, data->handle, data->nw_trace_type);
2266                 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2267                 {
2268                         dlt_log(LOG_ERR,"NWTSegmented: Could not send end segment.\n");
2269                 }
2270
2271                 /* Free resources */
2272                 free(data->header);
2273                 free(data->payload);
2274                 free(data);
2275         }
2276 }
2277
2278 void dlt_user_trace_network_segmented_thread_segmenter(s_segmented_data *data)
2279 {
2280         /* Segment the data and send the chunks */
2281         void *ptr                       = NULL;
2282         uint16_t offset         = 0;
2283         uint16_t sequence       = 0;
2284         do
2285         {
2286                 uint16_t len = 0;
2287                 if(offset + DLT_MAX_TRACE_SEGMENT_SIZE > data->payload_len)
2288                 {
2289                         len = data->payload_len - offset;
2290                 }
2291                 else
2292                 {
2293                         len = DLT_MAX_TRACE_SEGMENT_SIZE;
2294                 }
2295                 /* If payload size aligns perfectly with segment size, avoid sending empty segment */
2296                 if(len == 0)
2297                 {
2298                         break;
2299                 }
2300
2301                 ptr = data->payload + offset;
2302                 DltReturnValue err = dlt_user_trace_network_segmented_segment(data->id, data->handle, data->nw_trace_type, sequence++, len, ptr);
2303                 if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2304                 {
2305                         dlt_log(LOG_ERR,"NWTSegmented: Could not send segment. Aborting.\n");
2306                         break; // loop
2307                 }
2308                 offset += len;
2309         }while(ptr < data->payload + data->payload_len);
2310 }
2311
2312
2313 int dlt_user_trace_network_segmented(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2314 {
2315         /* Send as normal trace if possible */
2316         if(header_len+payload_len+sizeof(uint16_t) < DLT_USER_BUF_MAX_SIZE) {
2317                 return dlt_user_trace_network(handle, nw_trace_type, header_len, header, payload_len, payload);
2318         }
2319
2320         /* Allocate Memory */
2321         s_segmented_data *thread_data = malloc(sizeof(s_segmented_data));
2322         if(thread_data == NULL)
2323         {
2324                 return -1;
2325         }
2326         thread_data->header = malloc(header_len);
2327         if(thread_data->header == NULL)
2328         {
2329                 free(thread_data);
2330                 return -1;
2331         }
2332         thread_data->payload = malloc(payload_len);
2333         if(thread_data->payload == NULL)
2334         {
2335                 free(thread_data->header);
2336                 free(thread_data);
2337                 return -1;
2338         }
2339
2340         /* Copy data */
2341         thread_data->handle = handle;
2342         thread_data->nw_trace_type = nw_trace_type;
2343         thread_data->header_len = header_len;
2344         memcpy(thread_data->header, header, header_len);
2345         thread_data->payload_len = payload_len;
2346         memcpy(thread_data->payload, payload, payload_len);
2347
2348         /* Send start message */
2349         DltReturnValue err =    dlt_user_trace_network_segmented_start(&(thread_data->id),
2350                                                         thread_data->handle, thread_data->nw_trace_type,
2351                                                         thread_data->header_len, thread_data->header,
2352                                                         thread_data->payload_len);
2353         if(err == DLT_RETURN_BUFFER_FULL || err == DLT_RETURN_ERROR)
2354         {
2355                 dlt_log(LOG_ERR,"NWTSegmented: Could not send start segment. Aborting.\n");
2356                 free(thread_data->header);
2357                 free(thread_data->payload);
2358                 free(thread_data);
2359                 return -1;
2360         }
2361
2362         /* Open queue if it is not open */
2363         if(dlt_init_message_queue() < 0)
2364         {
2365                 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2366                 free(thread_data->header);
2367                 free(thread_data->payload);
2368                 free(thread_data);
2369
2370                 return -1;
2371         }
2372
2373         /* Add to queue */
2374         if(mq_send(dlt_user.dlt_segmented_queue_write_handle,
2375                         (char *)&thread_data, sizeof(s_segmented_data *), 1) < 0)
2376         {
2377                 if(errno == EAGAIN)
2378                 {
2379                         dlt_log(LOG_ERR, "NWTSegmented: Queue full. Message discarded.\n");
2380                 }
2381                 free(thread_data->header);
2382                 free(thread_data->payload);
2383                 free(thread_data);              
2384         char str[256];
2385         snprintf(str,255,"NWTSegmented: Could not write into queue: %s \n",strerror(errno));
2386         dlt_log(LOG_CRIT, str);
2387                 return -1;
2388         }
2389
2390         //thread_data will be freed by the receiver function
2391         //coverity[leaked_storage]
2392         return 0;
2393 }
2394
2395 int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
2396 {
2397         return dlt_user_trace_network_truncated(handle, nw_trace_type, header_len, header, payload_len, payload, 1);
2398 }
2399
2400 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)
2401 {
2402     DltContextData log;
2403
2404     if (dlt_user_initialised==0)
2405     {
2406         if (dlt_init()<0)
2407         {
2408             return -1;
2409         }
2410     }
2411
2412     if (dlt_user_log_init(handle, &log)==-1)
2413     {
2414                 return -1;
2415     }
2416
2417     if (handle==0)
2418     {
2419         return -1;
2420     }
2421
2422     /* Commented out because of DltNetworkTraceType:
2423
2424     if ((nw_trace_type<=0) || (nw_trace_type>0x15))
2425     {
2426         return -1;
2427     }
2428
2429     */
2430
2431     if (dlt_user.dlt_ll_ts==0)
2432     {
2433         return -1;
2434     }
2435
2436     if (handle->trace_status_ptr && *(handle->trace_status_ptr)==DLT_TRACE_STATUS_ON)
2437     {
2438
2439         log.args_num = 0;
2440         log.trace_status = nw_trace_type;
2441         log.size = 0;
2442
2443         if (header==0)
2444         {
2445             header_len=0;
2446         }
2447
2448         /* If truncation is allowed, check if we must do it */
2449         if(allow_truncate > 0 && (header_len+payload_len+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
2450         {
2451                 /* Identify as truncated */
2452                 if(dlt_user_log_write_string(&log, "NWTR") < 0)
2453                 {
2454                         return -1;
2455                 }
2456
2457             /* Write header and its length */
2458             if (dlt_user_log_write_raw(&log, header, header_len) < 0)
2459             {
2460                 return -1;
2461             }
2462
2463                 /* Write original size of payload */
2464             if(dlt_user_log_write_uint16(&log, payload_len) < 0)
2465             {
2466                 return -1;
2467             }
2468
2469                 /**
2470                  *  Calculate maximum avaialble space in sending buffer after headers.
2471                  */
2472
2473                 int truncated_payload_len = DLT_USER_BUF_MAX_SIZE -
2474                                 log.size - sizeof(uint16_t) - sizeof(uint32_t);
2475
2476             /* Write truncated payload */
2477             if (dlt_user_log_write_raw(&log, payload, truncated_payload_len) < 0)
2478             {
2479                         return -1;
2480             }
2481         }
2482         else /* Truncation not allowed or data short enough */
2483         {
2484             /* Write header and its length */
2485             if (dlt_user_log_write_raw(&log, header, header_len)==-1)
2486             {
2487                 return -1;
2488             }
2489
2490             if (payload==0)
2491             {
2492                 payload_len=0;
2493             }
2494
2495             /* Write payload and its length */
2496             if (dlt_user_log_write_raw(&log, payload, payload_len)==-1)
2497             {
2498                         return -1;
2499             }
2500         }
2501
2502         /* Send log */
2503         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
2504     }
2505
2506     return 0;
2507 }
2508
2509 int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
2510 {
2511     DltContextData log;
2512
2513     if (dlt_user.verbose_mode==0)
2514     {
2515         return -1;
2516     }
2517
2518     if ((handle==0) || (text==0))
2519     {
2520         return -1;
2521     }
2522
2523     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2524     {
2525         if (dlt_user_log_write_string(&log,text)==-1)
2526         {
2527                         return -1;
2528         }
2529         if (dlt_user_log_write_finish(&log)==-1)
2530         {
2531                 return -1;
2532         }
2533     }
2534
2535     return 0;
2536 }
2537
2538 int dlt_log_string_int(DltContext *handle,DltLogLevelType loglevel, const char *text, int data)
2539 {
2540     DltContextData log;
2541
2542     if (dlt_user.verbose_mode==0)
2543     {
2544         return -1;
2545     }
2546
2547     if ((handle==0) || (text==0))
2548     {
2549         return -1;
2550     }
2551
2552     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2553     {
2554         if (dlt_user_log_write_string(&log,text)==-1)
2555         {
2556                         return -1;
2557         }
2558         if (dlt_user_log_write_int(&log,data)==-1)
2559         {
2560                         return -1;
2561         }
2562         if (dlt_user_log_write_finish(&log)==-1)
2563         {
2564                         return -1;
2565         }
2566     }
2567
2568     return 0;
2569 }
2570
2571 int dlt_log_string_uint(DltContext *handle,DltLogLevelType loglevel, const char *text, unsigned int data)
2572 {
2573     DltContextData log;
2574
2575     if (dlt_user.verbose_mode==0)
2576     {
2577         return -1;
2578     }
2579
2580     if ((handle==0) || (text==0))
2581     {
2582         return -1;
2583     }
2584
2585     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2586     {
2587         if (dlt_user_log_write_string(&log,text)==-1)
2588         {
2589                         return -1;
2590         }
2591         if (dlt_user_log_write_uint(&log,data)==-1)
2592         {
2593                         return -1;
2594         }
2595         if (dlt_user_log_write_finish(&log)==-1)
2596         {
2597                         return -1;
2598         }
2599     }
2600
2601     return 0;
2602 }
2603
2604 int dlt_log_int(DltContext *handle,DltLogLevelType loglevel, int data)
2605 {
2606     DltContextData log;
2607
2608     if (dlt_user.verbose_mode==0)
2609     {
2610         return -1;
2611     }
2612
2613     if (handle==0)
2614     {
2615         return -1;
2616     }
2617
2618     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2619     {
2620         if (dlt_user_log_write_int(&log,data)==-1)
2621         {
2622                         return -1;
2623         }
2624         if (dlt_user_log_write_finish(&log)==-1)
2625         {
2626                         return -1;
2627         }
2628     }
2629
2630     return 0;
2631 }
2632
2633 int dlt_log_uint(DltContext *handle,DltLogLevelType loglevel, unsigned int data)
2634 {
2635     DltContextData log;
2636
2637     if (dlt_user.verbose_mode==0)
2638     {
2639         return -1;
2640     }
2641
2642     if (handle==0)
2643     {
2644         return -1;
2645     }
2646
2647     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2648     {
2649         if (dlt_user_log_write_uint(&log,data)==-1)
2650         {
2651                         return -1;
2652         }
2653         if (dlt_user_log_write_finish(&log)==-1)
2654         {
2655                         return -1;
2656         }
2657     }
2658
2659     return 0;
2660 }
2661
2662 int dlt_log_raw(DltContext *handle,DltLogLevelType loglevel, void *data,uint16_t length)
2663 {
2664     DltContextData log;
2665
2666     if (dlt_user.verbose_mode==0)
2667     {
2668         return -1;
2669     }
2670
2671     if (handle==0)
2672     {
2673         return -1;
2674     }
2675
2676     if (dlt_user_log_write_start(handle,&log,loglevel)>0)
2677     {
2678         if (dlt_user_log_write_raw(&log,data,length)==-1)
2679         {
2680                         return -1;
2681         }
2682         if (dlt_user_log_write_finish(&log)==-1)
2683         {
2684                         return -1;
2685         }
2686     }
2687
2688     return 0;
2689 }
2690
2691 int dlt_verbose_mode(void)
2692 {
2693     if (dlt_user_initialised==0)
2694     {
2695         if (dlt_init()<0)
2696         {
2697             return -1;
2698         }
2699     }
2700
2701     /* Switch to verbose mode */
2702     dlt_user.verbose_mode = 1;
2703
2704     return 0;
2705 }
2706
2707 int dlt_nonverbose_mode(void)
2708 {
2709     if (dlt_user_initialised==0)
2710     {
2711         if (dlt_init()<0)
2712         {
2713             return -1;
2714         }
2715     }
2716
2717     /* Switch to non-verbose mode */
2718     dlt_user.verbose_mode = 0;
2719
2720     return 0;
2721 }
2722
2723 int dlt_enable_local_print(void)
2724 {
2725     if (dlt_user_initialised==0)
2726     {
2727         if (dlt_init()<0)
2728         {
2729             return -1;
2730         }
2731     }
2732
2733     dlt_user.enable_local_print = 1;
2734
2735     return 0;
2736 }
2737
2738 int dlt_disable_local_print(void)
2739 {
2740     if (dlt_user_initialised==0)
2741     {
2742         if (dlt_init()<0)
2743         {
2744             return -1;
2745         }
2746     }
2747
2748     dlt_user.enable_local_print = 0;
2749
2750     return 0;
2751 }
2752
2753 void dlt_user_receiverthread_function(__attribute__((unused)) void *ptr)
2754 {
2755     prctl(PR_SET_NAME, "dlt_receiver", 0, 0, 0);
2756     while (1)
2757     {
2758         /* Check for new messages from DLT daemon */
2759         if (dlt_user_log_check_user_message()==-1)
2760         {
2761                         /* Critical error */
2762                         dlt_log(LOG_CRIT,"Receiver thread encountered error condition\n");
2763         }
2764
2765         usleep(DLT_USER_RECEIVE_DELAY); /* delay */
2766     }
2767 }
2768
2769 /* Private functions of user library */
2770
2771 int dlt_user_log_init(DltContext *handle, DltContextData *log)
2772 {
2773     if (dlt_user_initialised==0)
2774     {
2775         if (dlt_init()<0)
2776         {
2777             return -1;
2778         }
2779     }
2780
2781     log->handle = handle;
2782
2783     return 0;
2784 }
2785
2786 int dlt_user_queue_resend(void)
2787 {
2788         static unsigned char dlt_user_queue_resend_error_counter = 0;
2789
2790         if(dlt_user.dlt_log_handle < 0)
2791         {
2792                 // Fail silenty. FIFO is not open yet
2793                 return -1;
2794         }
2795     /**
2796      * Ask segmented thread to try emptying the buffer soon.
2797      * This will be freed in dlt_user_trace_network_segmented_thread
2798      * */
2799     s_segmented_data *resend_data = malloc(sizeof(s_segmented_data));
2800
2801     if (NULL == resend_data)
2802     {
2803         return -1;
2804     }
2805
2806     resend_data->payload_len = DLT_DELAYED_RESEND_INDICATOR_PATTERN;
2807
2808
2809
2810     /* Open queue if it is not open */
2811         if(dlt_init_message_queue() < 0)
2812         {
2813         if(!dlt_user_queue_resend_error_counter)
2814         {
2815                 // log error only when problem occurred first time
2816                 dlt_log(LOG_ERR, "NWTSegmented: Could not open queue.\n");
2817         }
2818         dlt_user_queue_resend_error_counter = 1;
2819         free(resend_data);
2820                 return -1;
2821         }
2822
2823     if(mq_send(dlt_user.dlt_segmented_queue_write_handle, (char *)&resend_data, sizeof(s_segmented_data *), 1) < 0)
2824     {
2825         if(!dlt_user_queue_resend_error_counter)
2826         {
2827                 // log error only when problem occurred first time
2828                         char str[255];
2829                         snprintf(str,254,"Could not request resending.: %s \n",strerror(errno));
2830                         dlt_log(LOG_CRIT, str);
2831         }
2832         dlt_user_queue_resend_error_counter = 1;
2833         free(resend_data);
2834         return -1;
2835     }
2836
2837     dlt_user_queue_resend_error_counter = 0;
2838
2839     //thread_data will be freed by the receiver function
2840     //coverity[leaked_storage]
2841     return 0;
2842 }
2843
2844 DltReturnValue dlt_user_log_send_log(DltContextData *log, int mtype)
2845 {
2846     DltMessage msg;
2847     DltUserHeader userheader;
2848     int32_t len;
2849
2850     DltReturnValue ret = DLT_RETURN_OK;
2851
2852     if (log==0)
2853     {
2854         return DLT_RETURN_ERROR;
2855     }
2856
2857     if (log->handle==0)
2858     {
2859         return DLT_RETURN_ERROR;
2860     }
2861
2862     if (dlt_user.appID[0]=='\0')
2863     {
2864         return DLT_RETURN_ERROR;
2865     }
2866
2867     if (log->handle->contextID[0]=='\0')
2868     {
2869         return DLT_RETURN_ERROR;
2870     }
2871
2872     if ((mtype<DLT_TYPE_LOG) || (mtype>DLT_TYPE_CONTROL))
2873     {
2874         return DLT_RETURN_ERROR;
2875     }
2876
2877     /* also for Trace messages */
2878 #ifdef DLT_SHM_ENABLE
2879     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_SHM)==-1)
2880 #else
2881     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
2882 #endif
2883     {
2884                 return DLT_RETURN_ERROR;
2885     }
2886
2887     if (dlt_message_init(&msg,0)==-1)
2888     {
2889         return DLT_RETURN_ERROR;
2890     }
2891
2892     msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
2893
2894     if (dlt_set_storageheader(msg.storageheader,dlt_user.ecuID)==-1)
2895     {
2896                 return DLT_RETURN_ERROR;
2897     }
2898
2899     msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
2900     msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_PROTOCOL_VERSION1 ;
2901
2902     if (dlt_user.verbose_mode)
2903     {
2904         /* In verbose mode, send extended header */
2905         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2906     }
2907     else
2908     {
2909         /* In non-verbose, send extended header if desired */
2910 #if (DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE==1)
2911         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2912 #endif
2913     }
2914
2915 #if (BYTE_ORDER==BIG_ENDIAN)
2916     msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
2917 #endif
2918
2919     msg.standardheader->mcnt = log->handle->mcnt++;
2920
2921     /* Set header extra parameters */
2922     dlt_set_id(msg.headerextra.ecu,dlt_user.ecuID);
2923     //msg.headerextra.seid = 0;
2924     msg.headerextra.tmsp = dlt_uptime();
2925
2926     if (dlt_message_set_extraparameters(&msg,0)==-1)
2927     {
2928         return DLT_RETURN_ERROR;
2929     }
2930
2931     /* Fill out extended header, if extended header should be provided */
2932     if (DLT_IS_HTYP_UEH(msg.standardheader->htyp))
2933     {
2934         /* with extended header */
2935         msg.extendedheader = (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)  );
2936
2937         switch (mtype)
2938         {
2939         case DLT_TYPE_LOG:
2940         {
2941             msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2942             break;
2943         }
2944         case DLT_TYPE_NW_TRACE:
2945         {
2946             msg.extendedheader->msin = (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT) | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2947             break;
2948         }
2949         default:
2950         {
2951                     /* This case should not occur */
2952             return DLT_RETURN_ERROR;
2953             break;
2954         }
2955         }
2956
2957         /* If in verbose mode, set flag in header for verbose mode */
2958         if (dlt_user.verbose_mode)
2959         {
2960             msg.extendedheader->msin |= DLT_MSIN_VERB;
2961         }
2962
2963         msg.extendedheader->noar = log->args_num;              /* number of arguments */
2964         dlt_set_id(msg.extendedheader->apid,dlt_user.appID);       /* application id */
2965         dlt_set_id(msg.extendedheader->ctid,log->handle->contextID);   /* context id */
2966
2967         msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2968     }
2969     else
2970     {
2971         /* without extended header */
2972         msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2973     }
2974
2975     len=msg.headersize - sizeof(DltStorageHeader) +log->size;
2976     if (len>UINT16_MAX)
2977     {
2978         dlt_log(LOG_CRIT,"Huge message discarded!\n");
2979         return DLT_RETURN_ERROR;
2980     }
2981
2982     msg.standardheader->len = DLT_HTOBE_16(len);
2983
2984     /* print to std out, if enabled */
2985     if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) &&
2986             (dlt_user.local_print_mode != DLT_PM_AUTOMATIC))
2987     {
2988         if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
2989         {
2990             if (dlt_user_print_msg(&msg, log)==-1)
2991             {
2992                                 return DLT_RETURN_ERROR;
2993             }
2994         }
2995     }
2996
2997     if (dlt_user.dlt_is_file)
2998     {
2999         /* log to file */
3000         ret=dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size);
3001         return ret;
3002     }
3003     else
3004     {
3005         /* Reattach to daemon if neccesary */
3006         dlt_user_log_reattach_to_daemon();
3007
3008         if (dlt_user.overflow_counter)
3009         {
3010             if (dlt_user_log_send_overflow()==0)
3011             {
3012                                 sprintf(str,"%u messages discarded!\n",dlt_user.overflow_counter);
3013                                 dlt_log(LOG_ERR, str);
3014                 dlt_user.overflow_counter=0;
3015             }
3016         }
3017
3018                 /* try to resent old data first */
3019                 ret = DLT_RETURN_OK;
3020                 if(dlt_user.dlt_log_handle!=-1)
3021                         ret = dlt_user_log_resend_buffer();
3022                 if(ret==DLT_RETURN_OK)
3023                 {
3024                         /* resend ok or nothing to resent */
3025 #ifdef DLT_SHM_ENABLE
3026                         if(dlt_user.dlt_log_handle!=-1)
3027                                 dlt_shm_push(&dlt_user.dlt_shm,msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3028                                                                                         log->buffer, log->size,0,0);                   
3029
3030                         /* log to FIFO */
3031                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
3032                                                                         &(userheader), sizeof(DltUserHeader),
3033                                                                         0, 0,
3034                                                                         0, 0);
3035 #else
3036                         /* log to FIFO */
3037 #ifdef DLT_TEST_ENABLE
3038                         if(dlt_user.corrupt_user_header) {
3039                                 userheader.pattern[0]=0xff;
3040                                 userheader.pattern[1]=0xff;
3041                                 userheader.pattern[2]=0xff;
3042                                 userheader.pattern[3]=0xff;
3043                         }
3044                         if(dlt_user.corrupt_message_size) {
3045                                 msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
3046                         }
3047 #endif
3048                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
3049                                                                         &(userheader), sizeof(DltUserHeader),
3050                                                                         msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3051                                                                         log->buffer, log->size);                
3052 #endif                  
3053                 }
3054                 
3055         /* store message in ringbuffer, if an error has occured */
3056         if (ret!=DLT_RETURN_OK)
3057         {
3058             DLT_SEM_LOCK();
3059
3060             if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3061                                 (unsigned char *)&(userheader), sizeof(DltUserHeader),
3062                                 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
3063                                 log->buffer, log->size)==-1)
3064                         {
3065                 if(dlt_user.overflow_counter==0)
3066                 {
3067
3068                         dlt_log(LOG_ERR,"Buffer full! Messages will be discarded.\n");
3069                 }
3070                 ret = DLT_RETURN_BUFFER_FULL;
3071                         }
3072
3073             DLT_SEM_FREE();
3074
3075                 // Fail silenty if FIFO is not open
3076             if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3077             {
3078                 ;//dlt_log(LOG_WARNING, "dlt_user_log_send_log: Failed to queue resending.\n");
3079             }
3080         }
3081
3082         switch (ret)
3083         {
3084         case DLT_RETURN_BUFFER_FULL:
3085         {
3086                 /* Buffer full */
3087             dlt_user.overflow_counter += 1;
3088                 return DLT_RETURN_BUFFER_FULL;
3089         }
3090         case DLT_RETURN_PIPE_FULL:
3091         {
3092             /* data could not be written */
3093             return DLT_RETURN_PIPE_FULL;
3094         }
3095         case DLT_RETURN_PIPE_ERROR:
3096         {
3097             /* handle not open or pipe error */
3098             close(dlt_user.dlt_log_handle);
3099             dlt_user.dlt_log_handle = -1;
3100
3101 #ifdef DLT_SHM_ENABLE
3102                         /* free shared memory */
3103                         dlt_shm_free_client(&dlt_user.dlt_shm);
3104 #endif
3105
3106             if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
3107             {
3108                 dlt_user_print_msg(&msg, log);
3109             }
3110
3111             return DLT_RETURN_PIPE_ERROR;
3112         }
3113         case DLT_RETURN_ERROR:
3114         {
3115             /* other error condition */
3116             return DLT_RETURN_ERROR;
3117         }
3118                 case DLT_RETURN_OK:
3119         {
3120                 return DLT_RETURN_OK;
3121         }
3122                 default:
3123                 {
3124                         /* This case should never occur. */
3125                         return DLT_RETURN_ERROR;
3126                 }
3127         }
3128     }
3129
3130     return DLT_RETURN_OK;
3131 }
3132
3133 int dlt_user_log_send_register_application(void)
3134 {
3135     DltUserHeader userheader;
3136     DltUserControlMsgRegisterApplication usercontext;
3137
3138     DltReturnValue ret;
3139
3140     if (dlt_user.appID[0]=='\0')
3141     {
3142         return -1;
3143     }
3144
3145     /* set userheader */
3146     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION)==-1)
3147     {
3148                 return -1;
3149     }
3150
3151     /* set usercontext */
3152     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3153     usercontext.pid = getpid();
3154
3155     if (dlt_user.application_description!=0)
3156     {
3157         usercontext.description_length = strlen(dlt_user.application_description);
3158     }
3159     else
3160     {
3161         usercontext.description_length = 0;
3162     }
3163
3164     if (dlt_user.dlt_is_file)
3165     {
3166         return 0;
3167     }
3168
3169     /* log to FIFO */
3170     ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication),dlt_user.application_description,usercontext.description_length);
3171
3172     /* store message in ringbuffer, if an error has occured */
3173     if (ret!=DLT_RETURN_OK)
3174     {
3175         DLT_SEM_LOCK();
3176
3177         if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3178                             (unsigned char *)&(userheader), sizeof(DltUserHeader),
3179                             (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterApplication),
3180                             (const unsigned char*)dlt_user.application_description, usercontext.description_length)==-1)
3181              {
3182                     dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3183                     DLT_SEM_FREE();
3184                     return -1;
3185              }
3186
3187         DLT_SEM_FREE();
3188
3189         if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3190         {
3191             ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_application: Failed to queue resending.\n");
3192         }
3193     }
3194
3195     return 0;
3196 }
3197
3198 int dlt_user_log_send_unregister_application(void)
3199 {
3200     DltUserHeader userheader;
3201     DltUserControlMsgUnregisterApplication usercontext;
3202
3203     DltReturnValue ret;
3204
3205     if (dlt_user.appID[0]=='\0')
3206     {
3207         return -1;
3208     }
3209
3210     /* set userheader */
3211     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION)==-1)
3212     {
3213         return -1;
3214     }
3215
3216     /* set usercontext */
3217     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3218     usercontext.pid = getpid();
3219
3220     if (dlt_user.dlt_is_file)
3221     {
3222         return 0;
3223     }
3224
3225     /* log to FIFO */
3226     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication));
3227     return ((ret==DLT_RETURN_OK)?0:-1);
3228 }
3229
3230 int dlt_user_log_send_register_context(DltContextData *log)
3231 {
3232     DltUserHeader userheader;
3233     DltUserControlMsgRegisterContext usercontext;
3234     DltReturnValue ret;
3235
3236     if (log==0)
3237     {
3238                 return -1;
3239     }
3240
3241     if (log->handle==0)
3242     {
3243         return -1;
3244     }
3245
3246     if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3247     {
3248         return -1;
3249     }
3250
3251     /* set userheader */
3252     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT)==-1)
3253     {
3254                 return -1;
3255     }
3256
3257     /* set usercontext */
3258     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3259     dlt_set_id(usercontext.ctid,log->handle->contextID);       /* context id */
3260     usercontext.log_level_pos = log->handle->log_level_pos;
3261     usercontext.pid = getpid();
3262
3263     usercontext.log_level = (int8_t)log->log_level;
3264     usercontext.trace_status = (int8_t)log->trace_status;
3265
3266     if (log->context_description!=0)
3267     {
3268         usercontext.description_length = strlen(log->context_description);
3269     }
3270     else
3271     {
3272                 usercontext.description_length = 0;
3273     }
3274
3275     if (dlt_user.dlt_is_file)
3276     {
3277         return 0;
3278     }
3279
3280     /* log to FIFO */
3281     ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext),log->context_description,usercontext.description_length);
3282
3283     /* store message in ringbuffer, if an error has occured */
3284     if (ret!=DLT_RETURN_OK)
3285     {
3286         DLT_SEM_LOCK();
3287
3288         if (dlt_buffer_push3(&(dlt_user.startup_buffer),
3289                             (unsigned char *)&(userheader), sizeof(DltUserHeader),
3290                             (const unsigned char*)&(usercontext), sizeof(DltUserControlMsgRegisterContext),
3291                             (const unsigned char*)log->context_description, usercontext.description_length)==-1)
3292              {
3293                     dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
3294                     DLT_SEM_FREE();
3295                     return -1;
3296              }
3297
3298         DLT_SEM_FREE();
3299
3300         if(dlt_user_queue_resend() < 0 && dlt_user.dlt_log_handle >= 0)
3301         {
3302             ;//dlt_log(LOG_WARNING, "dlt_user_log_send_register_context: Failed to queue resending.\n");
3303         }
3304     }
3305
3306     return 0;
3307
3308 }
3309
3310 int dlt_user_log_send_unregister_context(DltContextData *log)
3311 {
3312     DltUserHeader userheader;
3313     DltUserControlMsgUnregisterContext usercontext;
3314     DltReturnValue ret;
3315
3316     if (log==0)
3317     {
3318         return -1;
3319     }
3320
3321     if (log->handle==0)
3322     {
3323         return -1;
3324     }
3325
3326     if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
3327     {
3328         return -1;
3329     }
3330
3331     /* set userheader */
3332     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT)==-1)
3333     {
3334                 return -1;
3335     }
3336
3337     /* set usercontext */
3338     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
3339     dlt_set_id(usercontext.ctid,log->handle->contextID);       /* context id */
3340     usercontext.pid = getpid();
3341
3342     if (dlt_user.dlt_is_file)
3343     {
3344         return 0;
3345     }
3346
3347     /* log to FIFO */
3348     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext));
3349         return ((ret==DLT_RETURN_OK)?0:-1);
3350 }
3351
3352 int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
3353 {
3354     DltUserHeader userheader;
3355     DltUserControlMsgAppLogLevelTraceStatus usercontext;
3356         DltReturnValue ret;
3357
3358     if ((appid==0) || (appid[0]=='\0'))
3359     {
3360         return -1;
3361     }
3362
3363     /* Removed because of DltLogLevelType and DltTraceStatusType
3364
3365     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
3366     {
3367         return -1;
3368     }
3369
3370     if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
3371     {
3372         return -1;
3373     }
3374
3375     */
3376
3377     /* set userheader */
3378     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS)==-1)
3379     {
3380                 return -1;
3381     }
3382
3383     /* set usercontext */
3384     dlt_set_id(usercontext.apid,appid);       /* application id */
3385     usercontext.log_level = loglevel;
3386     usercontext.trace_status = tracestatus;
3387
3388     if (dlt_user.dlt_is_file)
3389     {
3390         return 0;
3391     }
3392
3393     /* log to FIFO */
3394     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus));
3395     return ((ret==DLT_RETURN_OK)?0:-1);
3396 }
3397
3398 int dlt_user_log_send_log_mode(DltUserLogMode mode)
3399 {
3400     DltUserHeader userheader;
3401     DltUserControlMsgLogMode logmode;
3402
3403     DltReturnValue ret;
3404
3405     /* set userheader */
3406     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE)==-1)
3407     {
3408         return -1;
3409     }
3410
3411     /* set data */
3412     logmode.log_mode = (unsigned char) mode;
3413
3414     if (dlt_user.dlt_is_file)
3415     {
3416         return 0;
3417     }
3418
3419     /* log to FIFO */
3420     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode));
3421     return ((ret==DLT_RETURN_OK)?0:-1);
3422 }
3423
3424 int dlt_user_print_msg(DltMessage *msg, DltContextData *log)
3425 {
3426     uint8_t *databuffer_tmp;
3427     int32_t datasize_tmp;
3428     int32_t databuffersize_tmp;
3429     static char text[DLT_USER_TEXT_LENGTH];
3430
3431     if ((msg==0) || (log==0))
3432     {
3433         return -1;
3434     }
3435
3436     /* Save variables before print */
3437     databuffer_tmp = msg->databuffer;
3438     datasize_tmp = msg->datasize;
3439     databuffersize_tmp = msg->databuffersize;
3440
3441     /* Act like a receiver, convert header back to host format */
3442     msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len);
3443     dlt_message_get_extraparameters(msg,0);
3444
3445     msg->databuffer = log->buffer;
3446     msg->datasize = log->size;
3447     msg->databuffersize = log->size;
3448
3449     /* Print message as ASCII */
3450     if (dlt_message_print_ascii(msg,text,DLT_USER_TEXT_LENGTH,0)==-1)
3451     {
3452                 return -1;
3453     }
3454
3455     /* Restore variables and set len to BE*/
3456     msg->databuffer = databuffer_tmp;
3457     msg->databuffersize = databuffersize_tmp;
3458     msg->datasize =  datasize_tmp;
3459
3460     msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
3461
3462     return 0;
3463 }
3464
3465 int dlt_user_log_check_user_message(void)
3466 {
3467     int offset=0;
3468     int leave_while=0;
3469
3470     uint32_t i;
3471
3472     DltUserHeader *userheader;
3473     DltReceiver *receiver = &(dlt_user.receiver);
3474
3475     DltUserControlMsgLogLevel *usercontextll;
3476     DltUserControlMsgInjection *usercontextinj;
3477     DltUserControlMsgLogState *userlogstate;
3478     unsigned char *userbuffer;
3479
3480     /* For delayed calling of injection callback, to avoid deadlock */
3481     DltUserInjectionCallback    delayed_injection_callback;
3482     unsigned char                               *delayed_inject_buffer = 0;
3483     uint32_t                                    delayed_inject_data_length = 0;
3484
3485     /* Ensure that callback is null before searching for it */
3486     delayed_injection_callback.injection_callback = 0;
3487     delayed_injection_callback.service_id = 0;
3488
3489     if (dlt_user.dlt_user_handle!=DLT_FD_INIT)
3490     {
3491         while (1)
3492         {
3493             if (dlt_receiver_receive_fd(receiver)<=0)
3494             {
3495                 /* No new message available */
3496                 return 0;
3497             }
3498
3499             /* look through buffer as long as data is in there */
3500             while (1)
3501             {
3502                 if (receiver->bytesRcvd < (int32_t)sizeof(DltUserHeader))
3503                 {
3504                     break;
3505                 }
3506
3507                 /* resync if necessary */
3508                 offset=0;
3509                 do
3510                 {
3511                     userheader = (DltUserHeader*) (receiver->buf+offset);
3512
3513                     /* Check for user header pattern */
3514                     if (dlt_user_check_userheader(userheader))
3515                     {
3516                         break;
3517                     }
3518                     offset++;
3519
3520                 }
3521                 while ((int32_t)(sizeof(DltUserHeader)+offset)<=receiver->bytesRcvd);
3522
3523                 /* Check for user header pattern */
3524                 if (dlt_user_check_userheader(userheader)<0 ||
3525                     dlt_user_check_userheader(userheader)==0)
3526                 {
3527                     break;
3528                 }
3529
3530                 /* Set new start offset */
3531                 if (offset>0)
3532                 {
3533                     receiver->buf+=offset;
3534                     receiver->bytesRcvd-=offset;
3535                 }
3536
3537                 switch (userheader->message)
3538                 {
3539                 case DLT_USER_MESSAGE_LOG_LEVEL:
3540                 {
3541                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel)))
3542                     {
3543                         leave_while=1;
3544                         break;
3545                     }
3546
3547                     usercontextll = (DltUserControlMsgLogLevel*) (receiver->buf+sizeof(DltUserHeader));
3548
3549                     /* Update log level and trace status */
3550                     if (usercontextll!=0)
3551                     {
3552                         DLT_SEM_LOCK();
3553
3554                         if ((usercontextll->log_level_pos >= 0) && (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries))
3555                         {
3556                             // printf("Store ll, ts\n");
3557                             if (dlt_user.dlt_ll_ts)
3558                             {
3559                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = usercontextll->log_level;
3560                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status = usercontextll->trace_status;
3561                                 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr)
3562                                         *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level_ptr) = usercontextll->log_level;
3563                                 if(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr)
3564                                         *(dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status_ptr) = usercontextll->trace_status;
3565                             }
3566                         }
3567
3568                         DLT_SEM_FREE();
3569                     }
3570
3571                     /* keep not read data in buffer */
3572                     if (dlt_receiver_remove(receiver,sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel))==-1)
3573                     {
3574                         return -1;
3575                     }
3576                 }
3577                 break;
3578                 case DLT_USER_MESSAGE_INJECTION:
3579                 {
3580                     /* At least, user header, user context, and service id and data_length of injected message is available */
3581                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)))
3582                     {
3583                         leave_while = 1;
3584                         break;
3585                     }
3586
3587                     usercontextinj = (DltUserControlMsgInjection*) (receiver->buf+sizeof(DltUserHeader));
3588                     userbuffer = (unsigned char*) (receiver->buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection));
3589
3590                     if (userbuffer!=0)
3591                     {
3592
3593                         if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))
3594                         {
3595                             leave_while = 1;
3596                             break;
3597                         }
3598
3599                         DLT_SEM_LOCK();
3600
3601                         if ((usercontextinj->data_length_inject>0) && (dlt_user.dlt_ll_ts))
3602                         {
3603                             /* Check if injection callback is registered for this context */
3604                             for (i=0; i<dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks;i++)
3605                             {
3606                                 if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) &&
3607                                         (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id == usercontextinj->service_id))
3608                                 {
3609                                         /* Prepare delayed injection callback call */
3610                                                                         if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback!=0)
3611                                                                         {
3612                                                                                 delayed_injection_callback.injection_callback = dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback;
3613                                                                                 delayed_injection_callback.service_id = usercontextinj->service_id;
3614                                                                                 delayed_inject_data_length = usercontextinj->data_length_inject;
3615                                                                                 delayed_inject_buffer = malloc(delayed_inject_data_length);
3616                                                                                 if(delayed_inject_buffer != 0) {
3617                                                                                         memcpy(delayed_inject_buffer, userbuffer, delayed_inject_data_length);
3618                                                                                 }
3619
3620                                                                         }
3621                                     break;
3622                                 }
3623                             }
3624                         }
3625
3626                         DLT_SEM_FREE();
3627
3628                         /* Delayed injection callback call */
3629                         if(delayed_inject_buffer != 0 && delayed_injection_callback.injection_callback != 0) {
3630                                 delayed_injection_callback.injection_callback(delayed_injection_callback.service_id, delayed_inject_buffer, delayed_inject_data_length);
3631                                 delayed_injection_callback.injection_callback = 0;
3632                                 free(delayed_inject_buffer);
3633                                 delayed_inject_buffer = NULL;
3634
3635                         }
3636
3637                         /* keep not read data in buffer */
3638                         if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))==-1)
3639                                                 {
3640                                                         return -1;
3641                                                 }
3642                     }
3643                 }
3644                 break;
3645                 case DLT_USER_MESSAGE_LOG_STATE:
3646                 {
3647                     /* At least, user header, user context, and service id and data_length of injected message is available */
3648                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))
3649                     {
3650                         leave_while = 1;
3651                         break;
3652                     }
3653
3654                     userlogstate = (DltUserControlMsgLogState*) (receiver->buf+sizeof(DltUserHeader));
3655                                         dlt_user.log_state = userlogstate->log_state;
3656
3657                                         /* keep not read data in buffer */
3658                                         if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))==-1)
3659                                         {
3660                                                 return -1;
3661                                         }
3662                 }
3663                 break;
3664                 default:
3665                 {
3666                     dlt_log(LOG_ERR,"Invalid user message type received!\n");
3667                     /* Ignore result */
3668                     dlt_receiver_remove(receiver,sizeof(DltUserHeader));
3669                                         /* In next invocation of while loop, a resync will be triggered if additional data was received */
3670                 }
3671                 break;
3672                 } /* switch() */
3673
3674                 if (leave_while==1)
3675                 {
3676                     leave_while=0;
3677                     break;
3678                 }
3679
3680             } /* while buffer*/
3681
3682             if (dlt_receiver_move_to_begin(receiver)==-1)
3683             {
3684                                 return -1;
3685             }
3686         } /* while receive */
3687     } /* if */
3688
3689     return DLT_RETURN_OK;
3690 }
3691
3692 int dlt_user_log_resend_buffer(void)
3693 {
3694         int num,count;
3695     int size;
3696         DltReturnValue ret;
3697         
3698         /* Send content of ringbuffer */
3699         DLT_SEM_LOCK();
3700         count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
3701         DLT_SEM_FREE();
3702
3703         for (num=0;num<count;num++)
3704         {
3705
3706                 DLT_SEM_LOCK();
3707                 size = dlt_buffer_copy(&(dlt_user.startup_buffer),dlt_user.resend_buffer,sizeof(dlt_user.resend_buffer));
3708
3709                 if (size>0)
3710                 {
3711 #ifdef DLT_SHM_ENABLE                                           
3712                         dlt_shm_push(&dlt_user.dlt_shm,dlt_user.resend_buffer+sizeof(DltUserHeader),size-sizeof(DltUserHeader),0,0,0,0);
3713
3714                         /* log to FIFO */
3715                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,sizeof(DltUserHeader),0,0,0,0);
3716 #else
3717                         /* log to FIFO */
3718                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle, dlt_user.resend_buffer,size,0,0,0,0);
3719 #endif
3720
3721                         /* in case of error, keep message in ringbuffer */                        
3722                         if (ret==DLT_RETURN_OK)
3723                         {
3724                                 dlt_buffer_remove(&(dlt_user.startup_buffer));
3725                         }
3726                         else
3727                         {
3728                                 /* keep message in ringbuffer */   
3729                                 DLT_SEM_FREE();
3730                                 return -1;
3731                         }
3732                 }
3733                 DLT_SEM_FREE();
3734         }
3735         
3736         return 0;
3737 }
3738
3739 void dlt_user_log_reattach_to_daemon(void)
3740 {
3741         uint32_t num,reregistered=0;
3742
3743         DltContext handle;
3744         DltContextData log_new;
3745
3746     if (dlt_user.dlt_log_handle<0)
3747     {
3748         dlt_user.dlt_log_handle=-1;
3749
3750         /* try to open pipe to dlt daemon */
3751         dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK);
3752         if (dlt_user.dlt_log_handle > 0)
3753         {
3754             if (dlt_user_log_init(&handle,&log_new)==-1)
3755             {
3756                 return;
3757             }
3758
3759 #ifdef DLT_SHM_ENABLE
3760                         /* init shared memory */
3761                         if (dlt_shm_init_client(&dlt_user.dlt_shm,DLT_SHM_KEY) < 0)
3762                         {
3763                                 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
3764                                 dlt_log(LOG_WARNING, str);
3765                                 //return 0; 
3766                         }   
3767 #endif
3768
3769             dlt_log(LOG_NOTICE, "Logging re-enabled!\n");
3770
3771             /* Re-register application */
3772             if (dlt_user_log_send_register_application()==-1)
3773             {
3774                 return;
3775             }
3776
3777             DLT_SEM_LOCK();
3778
3779             /* Re-register all stored contexts */
3780             for (num=0; num<dlt_user.dlt_ll_ts_num_entries; num++)
3781             {
3782                 /* Re-register stored context */
3783                 if ((dlt_user.appID[0]!='\0') && (dlt_user.dlt_ll_ts) && (dlt_user.dlt_ll_ts[num].contextID[0]!='\0'))
3784                 {
3785                     //dlt_set_id(log_new.appID, dlt_user.appID);
3786                     dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
3787                     handle.log_level_pos = num;
3788                     log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
3789
3790                     // Release the mutex for sending context registration:
3791                     // function  dlt_user_log_send_register_context() can take the mutex to write to the DLT buffer. => dead lock
3792                     DLT_SEM_FREE();
3793
3794                     log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
3795                     log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
3796
3797                     if (dlt_user_log_send_register_context(&log_new)==-1)
3798                     {
3799                         return;
3800                     }
3801
3802                     reregistered=1;
3803
3804                     // Lock again the mutex
3805                     // it is necessary in the for(;;) test, in order to have coherent dlt_user data all over the critical section.
3806                     DLT_SEM_LOCK();
3807
3808                 }
3809             }
3810
3811             DLT_SEM_FREE();
3812
3813             if (reregistered==1)
3814             {
3815                                 dlt_user_log_resend_buffer();
3816             }
3817         }
3818     }
3819 }
3820
3821 int dlt_user_log_send_overflow(void)
3822 {
3823     DltUserHeader userheader;
3824     DltUserControlMsgBufferOverflow userpayload;
3825     DltReturnValue ret;
3826
3827     /* set userheader */
3828     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW)==-1)
3829     {
3830         return -1;
3831     }
3832
3833     if (dlt_user.dlt_is_file)
3834     {
3835         return 0;
3836     }
3837
3838     /* set user message parameters */
3839     userpayload.overflow_counter = dlt_user.overflow_counter;
3840     dlt_set_id(userpayload.apid,dlt_user.appID);
3841
3842     /* log to FIFO */
3843     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader),
3844                               &(userpayload), sizeof(DltUserControlMsgBufferOverflow));
3845     return ((ret==DLT_RETURN_OK)?0:-1);
3846 }
3847
3848 int dlt_user_check_buffer(int *total_size, int *used_size)
3849 {
3850 #ifdef DLT_SHM_ENABLE
3851         *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm));
3852         *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm));
3853 #else
3854         *total_size = dlt_buffer_get_total_size(&(dlt_user.startup_buffer));
3855         *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer));
3856 #endif
3857         
3858         return 0; /* ok */
3859 }
3860
3861 #ifdef DLT_TEST_ENABLE
3862 void dlt_user_test_corrupt_user_header(int enable)
3863 {
3864     dlt_user.corrupt_user_header = enable;
3865 }
3866 void dlt_user_test_corrupt_message_size(int enable,int16_t size)
3867 {
3868     dlt_user.corrupt_message_size = enable;
3869     dlt_user.corrupt_message_size_size = size;
3870 }
3871 #endif
3872
3873