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