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