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