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