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