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