89daac27d7fa6f67939923c5d1785a31170d2929
[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
67 #include <stdlib.h> /* for getenv(), free(), atexit() */
68 #include <string.h> /* for strcmp(), strncmp(), strlen(), memset(), memcpy() */
69 #include <signal.h> /* for signal(), SIGPIPE, SIG_IGN */
70
71 #if !defined (__WIN32__)
72 #include <syslog.h> /* for LOG_... */
73 #include <semaphore.h>
74 #include <pthread.h>    /* POSIX Threads */
75 #endif
76
77 #include <sys/stat.h>
78 #include <fcntl.h>
79 #include <errno.h>
80
81 #include <sys/uio.h> /* writev() */
82
83 #include "dlt_user.h"
84 #include "dlt_user_shared.h"
85 #include "dlt_user_shared_cfg.h"
86 #include "dlt_user_cfg.h"
87
88 static DltUser dlt_user;
89 static int dlt_user_initialised = 0;
90
91 static char str[DLT_USER_BUFFER_LENGTH];
92
93 static sem_t dlt_mutex;
94 static pthread_t dlt_receiverthread_handle;
95 static pthread_attr_t dlt_receiverthread_attr;
96
97 /* Function prototypes for internally used functions */
98 static void dlt_user_receiverthread_function(void *ptr);
99 static void dlt_user_atexit_handler(void);
100 static int dlt_user_log_init(DltContext *handle, DltContextData *log);
101 static int dlt_user_log_send_log(DltContextData *log, int mtype);
102 static int dlt_user_log_send_register_application(void);
103 static int dlt_user_log_send_unregister_application(void);
104 static int dlt_user_log_send_register_context(DltContextData *log);
105 static int dlt_user_log_send_unregister_context(DltContextData *log);
106 static int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus);
107 static int dlt_user_log_send_log_mode(DltUserLogMode mode);
108 static int dlt_user_print_msg(DltMessage *msg, DltContextData *log);
109 static int dlt_user_log_check_user_message(void);
110 static int dlt_user_log_resend_buffer(void);
111 static void dlt_user_log_reattach_to_daemon(void);
112 static int dlt_user_log_send_overflow(void);
113
114 int dlt_user_check_library_version(const char *user_major_version,const char *user_minor_version){
115
116         char str[200];
117         char lib_major_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
118         char lib_minor_version[DLT_USER_MAX_LIB_VERSION_LENGTH];
119
120         dlt_get_major_version( lib_major_version);
121         dlt_get_minor_version( lib_minor_version);
122
123         if( (strcmp(lib_major_version,user_major_version)!=0) || (strcmp(lib_minor_version,user_minor_version)!=0))
124         {
125                 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);
126                 dlt_log(LOG_WARNING, str);
127                 return -1;
128         }
129         return 0;
130 }
131
132 int dlt_init(void)
133 {
134     char filename[DLT_USER_MAX_FILENAME_LENGTH];
135     int ret;
136
137     dlt_user_initialised = 1;
138
139     /* Initialize common part of dlt_init()/dlt_init_file() */
140     if (dlt_init_common()==-1)
141     {
142         dlt_user_initialised = 0;
143         return -1;
144     }
145
146     dlt_user.dlt_is_file = 0;
147     dlt_user.overflow = 0;
148 #ifdef DLT_SHM_ENABLE
149         memset(&(dlt_user.dlt_shm),0,sizeof(DltShm));
150 #endif
151
152     /* create and open DLT user FIFO */
153     sprintf(filename,"%s/dlt%d",DLT_USER_DIR,getpid());
154      
155     /* Try to delete existing pipe, ignore result of unlink */
156     unlink(filename);
157     
158     ret=mkfifo(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH  | S_IWOTH );
159     if (ret==-1)
160     {
161         sprintf(str,"Loging disabled, FIFO user %s cannot be created!\n",filename);
162         dlt_log(LOG_WARNING, str);
163         /* return 0; */ /* removed to prevent error, when FIFO already exists */
164     }
165
166     dlt_user.dlt_user_handle = open(filename, O_RDWR);
167     if (dlt_user.dlt_user_handle == -1)
168     {
169         sprintf(str,"Loging disabled, FIFO user %s cannot be opened!\n",filename);
170         dlt_log(LOG_WARNING, str);
171         unlink(filename);
172         return 0;
173     }
174
175     /* open DLT output FIFO */
176     dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK);
177     if (dlt_user.dlt_log_handle==-1)
178     {
179         sprintf(str,"Loging disabled, FIFO %s cannot be opened with open()!\n",DLT_USER_FIFO);
180         dlt_log(LOG_WARNING, str);
181         //return 0;
182     }
183         else
184         {
185 #ifdef DLT_SHM_ENABLE
186                 /* init shared memory */
187                 if (dlt_shm_init_client(&(dlt_user.dlt_shm),DLT_SHM_KEY) < 0)
188                 {
189                         sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
190                         dlt_log(LOG_WARNING, str);
191                         //return 0; 
192                 }   
193 #endif
194         }
195                 
196
197     if (dlt_receiver_init(&(dlt_user.receiver),dlt_user.dlt_user_handle, DLT_USER_RCVBUF_MAX_SIZE)==-1)
198         {
199         dlt_user_initialised = 0;
200         return -1;
201     }
202
203     /* Start receiver thread */
204     if (pthread_create(&(dlt_receiverthread_handle),
205                        0,
206                        (void *) &dlt_user_receiverthread_function,
207                        0)!=0)
208         {
209                 if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
210                 {
211                         dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
212                 }
213
214                 dlt_log(LOG_CRIT, "Can't create receiver thread!\n");
215                 dlt_user_initialised = 0;
216         return -1;
217         }
218
219     if (pthread_attr_destroy(&dlt_receiverthread_attr)!=0)
220         {
221                 dlt_log(LOG_WARNING, "Can't destroy thread attributes!\n");
222         }
223
224     return 0;
225 }
226
227 int dlt_init_file(const char *name)
228 {
229     dlt_user_initialised = 1;
230
231     /* Initialize common part of dlt_init()/dlt_init_file() */
232     if (dlt_init_common()==-1)
233     {
234         dlt_user_initialised = 0;
235         return -1;
236     }
237
238     dlt_user.dlt_is_file = 1;
239
240     /* open DLT output file */
241     dlt_user.dlt_log_handle = open(name,O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); /* mode: wb */
242     if (dlt_user.dlt_log_handle == -1)
243     {
244         sprintf(str,"Log file %s cannot be opened!\n",name);
245         dlt_log(LOG_ERR, str);
246         return -1;
247     }
248
249     return 0;
250 }
251
252 int dlt_init_common(void)
253 {
254     char *env_local_print;
255
256     /* Binary semaphore for threads */
257     if (sem_init(&dlt_mutex, 0, 1)==-1)
258     {
259         dlt_user_initialised = 0;
260         return -1;
261     }
262
263         /* set to unknown state of connected client */
264         dlt_user.log_state = -1;
265
266     dlt_user.dlt_log_handle=-1;
267     dlt_user.dlt_user_handle=-1;
268
269     dlt_set_id(dlt_user.ecuID,DLT_USER_DEFAULT_ECU_ID);
270     dlt_set_id(dlt_user.appID,"");
271
272     dlt_user.application_description = 0;
273
274     /* Verbose mode is enabled by default */
275     dlt_user.verbose_mode = 1;
276
277     /* Local print is disabled by default */
278     dlt_user.enable_local_print = 0;
279
280     dlt_user.local_print_mode = DLT_PM_UNSET;
281
282     env_local_print = getenv(DLT_USER_ENV_LOCAL_PRINT_MODE);
283     if (env_local_print)
284     {
285         if (strcmp(env_local_print,"AUTOMATIC")==0)
286         {
287             dlt_user.local_print_mode = DLT_PM_AUTOMATIC;
288         }
289         else if (strcmp(env_local_print,"FORCE_ON")==0)
290         {
291             dlt_user.local_print_mode = DLT_PM_FORCE_ON;
292         }
293         else if (strcmp(env_local_print,"FORCE_OFF")==0)
294         {
295             dlt_user.local_print_mode = DLT_PM_FORCE_OFF;
296         }
297     }
298
299     /* Initialize LogLevel/TraceStatus field */
300     dlt_user.dlt_ll_ts = 0;
301     dlt_user.dlt_ll_ts_max_num_entries = 0;
302     dlt_user.dlt_ll_ts_num_entries = 0;
303
304     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)
305     {
306                 dlt_user_initialised = 0;
307         return -1;
308     }
309
310     signal(SIGPIPE,SIG_IGN);                  /* ignore pipe signals */
311
312     atexit(dlt_user_atexit_handler);
313
314 #ifdef DLT_TEST_ENABLE
315     dlt_user.corrupt_user_header = 0;
316     dlt_user.corrupt_message_size = 0;
317     dlt_user.corrupt_message_size_size = 0;
318 #endif
319
320     return 0;
321 }
322
323 void dlt_user_atexit_handler(void)
324 {
325
326         /* Try to resend potential log messages in the user buffer */
327         int count = dlt_user_atexit_blow_out_user_buffer();
328
329         if(count != 0){
330                 char tmp[256];
331                 sprintf(tmp,"Lost log messages in user buffer when exiting: %i\n",count);
332                 dlt_log(LOG_ERR, tmp);
333         }
334
335     /* Unregister app (this also unregisters all contexts in daemon) */
336     /* Ignore return value */
337     dlt_unregister_app();
338
339     /* Cleanup */
340     /* Ignore return value */
341     dlt_free();
342 }
343
344 int dlt_user_atexit_blow_out_user_buffer(void){
345
346         int count,ret;
347
348         uint32_t exitTime = dlt_uptime() + DLT_USER_ATEXIT_RESEND_BUFFER_EXIT_TIMEOUT;
349
350         while(dlt_uptime() < exitTime ){
351
352                 ret = dlt_user_log_resend_buffer();
353
354                 if(ret == 0)
355                 {
356                                 return 0;
357                 }
358
359                 usleep(DLT_USER_ATEXIT_RESEND_BUFFER_SLEEP);
360         }
361
362         DLT_SEM_LOCK();
363         count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
364         DLT_SEM_FREE();
365
366         return count;
367 }
368
369 int dlt_free(void)
370 {
371     uint32_t i;
372         char filename[DLT_USER_MAX_FILENAME_LENGTH];
373
374     if (dlt_user_initialised==0)
375     {
376         return -1;
377     }
378
379     if (dlt_receiverthread_handle)
380     {
381         /* Ignore return value */
382         pthread_cancel(dlt_receiverthread_handle);
383     }
384
385     if (dlt_user.dlt_user_handle!=-1)
386     {
387         sprintf(filename,"/tmp/dlt%d",getpid());
388
389         close(dlt_user.dlt_user_handle);
390         dlt_user.dlt_user_handle=-1;
391
392         unlink(filename);
393     }
394
395 #ifdef DLT_SHM_ENABLE
396         /* free shared memory */
397         dlt_shm_free_client(&dlt_user.dlt_shm);
398 #endif
399
400     if (dlt_user.dlt_log_handle!=-1)
401     {
402         /* close log file/output fifo to daemon */
403         close(dlt_user.dlt_log_handle);
404         dlt_user.dlt_log_handle = -1;
405     }
406
407         /* Ignore return value */
408     dlt_receiver_free(&(dlt_user.receiver));
409
410         /* Ignore return value */
411     dlt_buffer_free_dynamic(&(dlt_user.startup_buffer));
412
413     if (dlt_user.dlt_ll_ts)
414     {
415         for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
416         {
417             if (dlt_user.dlt_ll_ts[i].injection_table!=0)
418             {
419                 free(dlt_user.dlt_ll_ts[i].injection_table);
420                 dlt_user.dlt_ll_ts[i].injection_table = 0;
421             }
422             dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
423         }
424
425         free(dlt_user.dlt_ll_ts);
426         dlt_user.dlt_ll_ts = 0;
427         dlt_user.dlt_ll_ts_max_num_entries = 0;
428         dlt_user.dlt_ll_ts_num_entries = 0;
429     }
430
431     dlt_user_initialised = 0;
432
433     return 0;
434 }
435
436 int dlt_check_library_version(const char * user_major_version,const char * user_minor_version)
437 {
438         return dlt_user_check_library_version(user_major_version, user_minor_version);
439 }
440
441 int dlt_register_app(const char *appid, const char * description)
442 {
443     int ret;
444
445     if (dlt_user_initialised==0)
446     {
447         if (dlt_init()<0)
448         {
449             return -1;
450         }
451     }
452
453     if ((appid==0) || (appid[0]=='\0'))
454     {
455         return -1;
456     }
457
458     DLT_SEM_LOCK();
459
460     /* Store locally application id and application description */
461     dlt_set_id(dlt_user.appID, appid);
462
463     if (dlt_user.application_description!=0)
464     {
465         free(dlt_user.application_description);
466     }
467
468     dlt_user.application_description = 0;
469
470     if (description!=0)
471     {
472         dlt_user.application_description= malloc(strlen(description)+1);
473         strncpy(dlt_user.application_description, description, strlen(description));
474
475         /* Terminate transmitted string with 0 */
476         dlt_user.application_description[strlen(description)]='\0';
477     }
478
479     DLT_SEM_FREE();
480
481     ret = dlt_user_log_send_register_application();
482
483     return ret;
484 }
485 int dlt_register_context(DltContext *handle, const char *contextid, const char * description)
486 {
487     if (dlt_user_initialised==0)
488     {
489         if (dlt_init()<0)
490         {
491             return -1;
492         }
493     }
494
495     DLT_SEM_LOCK();
496
497     if (dlt_user.appID[0]=='\0')
498     {
499         dlt_log(LOG_ERR, "no application registered!\n");
500
501         DLT_SEM_FREE();
502         return -1;
503     }
504
505     if ((contextid==0) || (contextid[0]=='\0'))
506     {
507         DLT_SEM_FREE();
508         return -1;
509     }
510
511     DLT_SEM_FREE();
512
513     return dlt_register_context_ll_ts(handle, contextid, description, DLT_USER_LOG_LEVEL_NOT_SET, DLT_USER_TRACE_STATUS_NOT_SET);
514 }
515
516 int dlt_register_context_ll_ts(DltContext *handle, const char *contextid, const char * description, int loglevel, int tracestatus)
517 {
518     DltContextData log;
519     uint32_t i;
520     int registered,ret;
521     char ctid[DLT_ID_SIZE+1];
522
523     if (dlt_user_initialised==0)
524     {
525         if (dlt_init()<0)
526         {
527             return -1;
528         }
529     }
530
531     DLT_SEM_LOCK();
532
533     if (dlt_user.appID[0]=='\0')
534     {
535         dlt_log(LOG_ERR, "no application registered!\n");
536
537         DLT_SEM_FREE();
538         return -1;
539     }
540
541     DLT_SEM_FREE();
542
543     if ((contextid==0) || (contextid[0]=='\0'))
544     {
545         return -1;
546     }
547
548     if ((loglevel<DLT_USER_LOG_LEVEL_NOT_SET) || (loglevel>DLT_LOG_VERBOSE) || (loglevel==DLT_LOG_DEFAULT))
549     {
550         return -1;
551     }
552
553     if ((tracestatus<DLT_USER_TRACE_STATUS_NOT_SET) || (tracestatus>DLT_TRACE_STATUS_ON) || (tracestatus==DLT_TRACE_STATUS_DEFAULT))
554     {
555         return -1;
556     }
557
558     if (dlt_user_log_init(handle, &log)==-1)
559     {
560         return -1;
561     }
562
563     /* Reset message counter */
564     handle->mcnt = 0;
565
566     /* Store context id in log level/trace status field */
567
568     /* Check if already registered, else register context */
569     DLT_SEM_LOCK();
570
571     registered=0;
572     for (i=0;i<dlt_user.dlt_ll_ts_num_entries;i++)
573     {
574         if (dlt_user.dlt_ll_ts)
575         {
576             if (memcmp(dlt_user.dlt_ll_ts[i].contextID, contextid,DLT_ID_SIZE)==0)
577             {
578                 registered=1;
579
580                 memset(ctid,0,(DLT_ID_SIZE+1));
581                 dlt_print_id(ctid, contextid);
582
583                 sprintf(str,"context '%s' already registered!\n",ctid);
584                 dlt_log(LOG_WARNING, str);
585
586                 break;
587             }
588         }
589     }
590
591     if (registered==0)
592     {
593         /* Allocate or expand context array */
594         if (dlt_user.dlt_ll_ts == 0)
595         {
596             dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*DLT_USER_CONTEXT_ALLOC_SIZE);
597             if (dlt_user.dlt_ll_ts==0)
598             {
599                 DLT_SEM_FREE();
600                 return -1;
601             }
602
603             dlt_user.dlt_ll_ts_max_num_entries = DLT_USER_CONTEXT_ALLOC_SIZE;
604
605             /* Initialize new entries */
606             for (i=0;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
607             {
608                 dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
609
610                 /* At startup, logging and tracing is locally enabled */
611                 /* the correct log level/status is set after received from daemon */
612                 dlt_user.dlt_ll_ts[i].log_level    = DLT_USER_INITIAL_LOG_LEVEL;
613                 dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
614
615                 dlt_user.dlt_ll_ts[i].context_description = 0;
616
617                 dlt_user.dlt_ll_ts[i].injection_table = 0;
618                 dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
619             }
620         }
621         else
622         {
623             if ((dlt_user.dlt_ll_ts_num_entries%DLT_USER_CONTEXT_ALLOC_SIZE)==0)
624             {
625                 /* allocate memory in steps of DLT_USER_CONTEXT_ALLOC_SIZE, e.g. 500 */
626                 dlt_ll_ts_type *old;
627                 old = dlt_user.dlt_ll_ts;
628                 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;
629                 dlt_user.dlt_ll_ts = (dlt_ll_ts_type*) malloc(sizeof(dlt_ll_ts_type)*
630                                      dlt_user.dlt_ll_ts_max_num_entries);
631                 if (dlt_user.dlt_ll_ts==0)
632                 {
633                     DLT_SEM_FREE();
634                     return -1;
635                 }
636
637                 memcpy(dlt_user.dlt_ll_ts,old,sizeof(dlt_ll_ts_type)*dlt_user.dlt_ll_ts_num_entries);
638                 free(old);
639
640                 /* Initialize new entries */
641                 for (i=dlt_user.dlt_ll_ts_num_entries;i<dlt_user.dlt_ll_ts_max_num_entries;i++)
642                 {
643                     dlt_set_id(dlt_user.dlt_ll_ts[i].contextID,"");
644
645                     /* At startup, logging and tracing is locally enabled */
646                     /* the correct log level/status is set after received from daemon */
647                     dlt_user.dlt_ll_ts[i].log_level    = DLT_USER_INITIAL_LOG_LEVEL;
648                     dlt_user.dlt_ll_ts[i].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
649
650                     dlt_user.dlt_ll_ts[i].context_description = 0;
651
652                     dlt_user.dlt_ll_ts[i].injection_table = 0;
653                     dlt_user.dlt_ll_ts[i].nrcallbacks     = 0;
654                 }
655             }
656         }
657
658         /* Store locally context id and context description */
659         dlt_set_id(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].contextID, contextid);
660
661         if (dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description!=0)
662         {
663             free(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description);
664         }
665
666         dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = 0;
667
668         if (description!=0)
669         {
670                 int desc_lne = strlen(description);
671             dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = malloc(desc_len+1);
672             strncpy(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description, description, strlen(desc_len));
673
674             /* Terminate transmitted string with 0 */
675             dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description[desc_len]='\0';
676         }
677
678         if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
679         {
680             dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = loglevel;
681         }
682
683         if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
684         {
685             dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
686         }
687
688         /* Prepare transfer struct */
689         //dlt_set_id(log->appID, dlt_user.appID);
690         dlt_set_id(handle->contextID, contextid);
691         handle->log_level_pos = dlt_user.dlt_ll_ts_num_entries;
692
693         log.context_description = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description;
694
695         if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
696         {
697             log.log_level = loglevel;
698         }
699         else
700         {
701             log.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
702         }
703
704         if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
705         {
706             log.trace_status = tracestatus;
707         }
708         else
709         {
710             log.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
711         }
712
713         dlt_user.dlt_ll_ts_num_entries++;
714
715         DLT_SEM_FREE();
716
717         ret=dlt_user_log_send_register_context(&log);
718     }
719     else
720     {
721         DLT_SEM_FREE();
722
723         ret=-1;
724     }
725
726     return ret;
727 }
728
729 int dlt_unregister_app(void)
730 {
731     int ret;
732
733     if (dlt_user_initialised==0)
734     {
735         return -1;
736     }
737
738     /* Inform daemon to unregister application and all of its contexts */
739     ret = dlt_user_log_send_unregister_application();
740
741     DLT_SEM_LOCK();
742
743     /* Clear and free local stored application information */
744     dlt_set_id(dlt_user.appID, "");
745
746     if (dlt_user.application_description!=0)
747     {
748         free(dlt_user.application_description);
749     }
750
751     dlt_user.application_description = 0;
752
753     DLT_SEM_FREE();
754
755     return ret;
756 }
757
758 int dlt_unregister_context(DltContext *handle)
759 {
760     DltContextData log;
761     int ret;
762
763     if (dlt_user_initialised==0)
764     {
765         return -1;
766     }
767
768     if (dlt_user_log_init(handle, &log) == -1)
769     {
770                 return -1;
771     }
772
773     DLT_SEM_LOCK();
774
775     if (dlt_user.dlt_ll_ts)
776     {
777         /* Clear and free local stored context information */
778         dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, "");
779
780         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
781         dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
782
783         if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description!=0)
784         {
785             free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
786         }
787
788         dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = 0;
789
790         if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table)
791         {
792             free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
793             dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = 0;
794         }
795
796         dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks     = 0;
797     }
798
799     DLT_SEM_FREE();
800
801     /* Inform daemon to unregister context */
802     ret = dlt_user_log_send_unregister_context(&log);
803
804     return ret;
805 }
806
807 int dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus)
808 {
809     uint32_t i;
810     int ret;
811
812     if (dlt_user_initialised==0)
813     {
814         if (dlt_init()<0)
815         {
816             return -1;
817         }
818     }
819
820     /* Removed because of DltLogLevelType and DltTraceStatusType
821
822     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
823     {
824         return -1;
825     }
826
827     if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
828     {
829         return -1;
830     }
831
832     if (dlt_user.dlt_ll_ts==0)
833     {
834         return -1;
835     }
836
837     */
838
839     DLT_SEM_LOCK();
840
841     /* Update local structures */
842     for (i=0; i<dlt_user.dlt_ll_ts_num_entries;i++)
843     {
844         dlt_user.dlt_ll_ts[i].log_level = loglevel;
845         dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
846     }
847
848     DLT_SEM_FREE();
849
850     /* Inform DLT server about update */
851     ret = dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus);
852
853     return ret;
854 }
855
856 int dlt_get_log_state()
857 {
858         return dlt_user.log_state;
859 }
860
861 int dlt_set_log_mode(DltUserLogMode mode)
862 {
863     if (dlt_user_initialised==0)
864     {
865         if (dlt_init()<0)
866         {
867             return -1;
868         }
869     }
870
871         return dlt_user_log_send_log_mode(mode);
872 }
873
874 int dlt_forward_msg(void *msgdata,size_t size)
875 {
876     DltUserHeader userheader;
877     DltReturnValue ret;
878
879     if ((msgdata==0) || (size==0))
880     {
881         return -1;
882     }
883
884     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
885     {
886         /* Type of internal user message; same value for Trace messages */
887         return -1;
888     }
889
890     if (dlt_user.dlt_is_file)
891     {
892         /* log to file */
893         ret = dlt_user_log_out2(dlt_user.dlt_log_handle, msgdata, size, 0, 0);
894         return ((ret==DLT_RETURN_OK)?0:-1);
895     }
896     else
897     {
898         /* Reattach to daemon if neccesary */
899         dlt_user_log_reattach_to_daemon();
900
901         if (dlt_user.overflow)
902         {
903             if (dlt_user_log_send_overflow()==0)
904             {
905                 dlt_user.overflow=0;
906             }
907         }
908
909         /* log to FIFO */
910         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
911                                 &(userheader), sizeof(DltUserHeader),
912                                 msgdata, size, 0, 0);
913
914         /* store message in ringbuffer, if an error has occured */
915         if (ret!=DLT_RETURN_OK)
916         {
917             DLT_SEM_LOCK();
918
919             if (dlt_buffer_push3(&(dlt_user.startup_buffer),
920                                 (unsigned char *)&(userheader), sizeof(DltUserHeader),
921                                  msgdata, size, 0, 0)==-1)
922                         {
923                                 dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
924                         }
925
926             DLT_SEM_FREE();
927         }
928
929         switch (ret)
930         {
931         case DLT_RETURN_PIPE_FULL:
932         {
933             /* data could not be written */
934             dlt_user.overflow = 1;
935             return -1;
936         }
937         case DLT_RETURN_PIPE_ERROR:
938         {
939             /* handle not open or pipe error */
940             close(dlt_user.dlt_log_handle);
941             dlt_user.dlt_log_handle = -1;
942
943             return -1;
944         }
945         case DLT_RETURN_ERROR:
946         {
947             /* other error condition */
948             return -1;
949         }
950         case DLT_RETURN_OK:
951         {
952                 return 0;
953         }
954                 default:
955                 {
956                         /* This case should not occur */
957                         return -1;
958                 }
959         }
960     }
961
962     return 0;
963 }
964
965 /* ********************************************************************************************* */
966
967 int dlt_user_log_write_start(DltContext *handle, DltContextData *log,DltLogLevelType loglevel)
968 {
969     return dlt_user_log_write_start_id(handle,log,loglevel,DLT_USER_DEFAULT_MSGID);
970 }
971
972 int dlt_user_log_write_start_id(DltContext *handle, DltContextData *log,DltLogLevelType loglevel, uint32_t messageid)
973 {
974     uint32_t mid;
975
976     if (dlt_user_initialised==0)
977     {
978         if (dlt_init()<0)
979         {
980             return -1;
981         }
982     }
983
984     if (dlt_user_log_init(handle, log)==-1)
985     {
986                 return -1;
987     }
988
989     if (log==0)
990     {
991         return -1;
992     }
993
994     /* Removed because of DltLogLevelType
995
996     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
997     {
998         return -1;
999     }
1000
1001     */
1002
1003     mid = messageid;
1004
1005     log->args_num = 0;
1006     log->log_level = loglevel;
1007     log->size = 0;
1008
1009     if (dlt_user.dlt_ll_ts==0)
1010     {
1011         return -1;
1012     }
1013
1014     DLT_SEM_LOCK();
1015
1016     if ((log->log_level<=(int)(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level) ) && (log->log_level!=0))
1017     {
1018         DLT_SEM_FREE();
1019
1020         /* In non-verbose mode, insert message id */
1021         if (dlt_user.verbose_mode==0)
1022         {
1023             if ((sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1024             {
1025                 return -1;
1026             }
1027             /* Write message id */
1028             memcpy(log->buffer,&(mid),sizeof(uint32_t));
1029             log->size = sizeof(uint32_t);
1030
1031             /* as the message id is part of each message in non-verbose mode,
1032                it doesn't increment the argument counter in extended header (if used) */
1033         }
1034         return 1;
1035     }
1036     else
1037     {
1038         DLT_SEM_FREE();
1039         return 0;
1040     }
1041
1042     return -1;
1043 }
1044
1045 int dlt_user_log_write_finish(DltContextData *log)
1046 {
1047     if (log==0)
1048     {
1049         return -1;
1050     }
1051
1052     return dlt_user_log_send_log(log, DLT_TYPE_LOG);
1053 }
1054
1055 int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length)
1056 {
1057     uint16_t arg_size;
1058     uint32_t type_info;
1059
1060     if (log==0)
1061     {
1062         return -1;
1063     }
1064
1065     if ((log->size+length+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1066     {
1067         return -1;
1068     }
1069
1070     if (dlt_user.verbose_mode)
1071     {
1072         if ((log->size+length+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1073         {
1074             return -1;
1075         }
1076
1077         /* Transmit type information */
1078         type_info = DLT_TYPE_INFO_RAWD;
1079
1080         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1081         log->size += sizeof(uint32_t);
1082
1083     }
1084
1085     /* First transmit length of raw data, then the raw data itself */
1086     arg_size = (uint16_t)length;
1087
1088     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1089     log->size += sizeof(uint16_t);
1090
1091     memcpy((log->buffer)+log->size,data,arg_size);
1092     log->size += arg_size;
1093
1094     log->args_num ++;
1095
1096     return 0;
1097 }
1098
1099 int dlt_user_log_write_float32(DltContextData *log, float32_t data)
1100 {
1101     uint32_t type_info;
1102
1103     if (log==0)
1104     {
1105         return -1;
1106     }
1107
1108     if (sizeof(float32_t)!=4)
1109     {
1110         return -1;
1111     }
1112
1113     if ((log->size+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1114     {
1115         return -1;
1116     }
1117
1118     if (dlt_user.verbose_mode)
1119     {
1120         if ((log->size+sizeof(uint32_t)+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1121         {
1122             return -1;
1123         }
1124
1125         type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
1126
1127         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1128         log->size += sizeof(uint32_t);
1129     }
1130
1131     memcpy((log->buffer)+log->size,&data, sizeof(float32_t));
1132     log->size += sizeof(float32_t);
1133
1134     log->args_num ++;
1135
1136     return 0;
1137 }
1138
1139 int dlt_user_log_write_float64(DltContextData *log, float64_t data)
1140 {
1141     uint32_t type_info;
1142
1143     if (log==0)
1144     {
1145         return -1;
1146     }
1147
1148     if (sizeof(float64_t)!=8)
1149     {
1150         return -1;
1151     }
1152
1153     if ((log->size+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1154     {
1155         return -1;
1156     }
1157
1158     if (dlt_user.verbose_mode)
1159     {
1160         if ((log->size+sizeof(uint32_t)+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1161         {
1162             return -1;
1163         }
1164
1165         type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
1166
1167         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1168         log->size += sizeof(uint32_t);
1169     }
1170
1171     memcpy((log->buffer)+log->size,&data, sizeof(float64_t));
1172     log->size += sizeof(float64_t);
1173
1174     log->args_num ++;
1175
1176     return 0;
1177 }
1178
1179 int dlt_user_log_write_uint( DltContextData *log, unsigned int data)
1180 {
1181     if (log==0)
1182     {
1183         return -1;
1184     }
1185
1186     switch (sizeof(unsigned int))
1187     {
1188     case 1:
1189     {
1190         return dlt_user_log_write_uint8(log, (uint8_t)data);
1191         break;
1192     }
1193     case 2:
1194     {
1195         return dlt_user_log_write_uint16(log, (uint16_t)data);
1196         break;
1197     }
1198     case 4:
1199     {
1200         return dlt_user_log_write_uint32(log, (uint32_t)data);
1201         break;
1202     }
1203     case 8:
1204     {
1205         return dlt_user_log_write_uint64(log, (uint64_t)data);
1206                 break;
1207     }
1208     default:
1209     {
1210         return -1;
1211         break;
1212     }
1213     }
1214
1215     return 0;
1216 }
1217
1218 int dlt_user_log_write_uint8(DltContextData *log, uint8_t data)
1219 {
1220     uint32_t type_info;
1221
1222     if (log==0)
1223     {
1224         return -1;
1225     }
1226
1227     if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1228     {
1229         return -1;
1230     }
1231
1232     if (dlt_user.verbose_mode)
1233     {
1234         if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1235         {
1236             return -1;
1237         }
1238
1239         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
1240
1241         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1242         log->size += sizeof(uint32_t);
1243     }
1244
1245     memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1246     log->size += sizeof(uint8_t);
1247
1248     log->args_num ++;
1249
1250     return 0;
1251 }
1252
1253 int dlt_user_log_write_uint16(DltContextData *log, uint16_t data)
1254 {
1255     uint32_t type_info;
1256
1257     if (log==0)
1258     {
1259         return -1;
1260     }
1261
1262     if ((log->size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1263     {
1264         return -1;
1265     }
1266
1267     if (dlt_user.verbose_mode)
1268     {
1269         if ((log->size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1270         {
1271             return -1;
1272         }
1273
1274         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
1275
1276         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1277         log->size += sizeof(uint32_t);
1278     }
1279
1280     memcpy((log->buffer)+log->size,&data,sizeof(uint16_t));
1281     log->size += sizeof(uint16_t);
1282
1283     log->args_num ++;
1284
1285     return 0;
1286 }
1287
1288 int dlt_user_log_write_uint32(DltContextData *log, uint32_t data)
1289 {
1290     uint32_t type_info;
1291
1292     if (log==0)
1293     {
1294         return -1;
1295     }
1296
1297     if ((log->size+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1298     {
1299         return -1;
1300     }
1301
1302     if (dlt_user.verbose_mode)
1303     {
1304         if ((log->size+sizeof(uint32_t)+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1305         {
1306             return -1;
1307         }
1308
1309         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
1310
1311         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1312         log->size += sizeof(uint32_t);
1313     }
1314
1315     memcpy((log->buffer)+log->size,&data, sizeof(uint32_t));
1316     log->size += sizeof(uint32_t);
1317
1318     log->args_num ++;
1319
1320     return 0;
1321 }
1322
1323 int dlt_user_log_write_uint64(DltContextData *log, uint64_t data)
1324 {
1325     uint32_t type_info;
1326
1327     if (log==0)
1328     {
1329         return -1;
1330     }
1331
1332     if ((log->size+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1333     {
1334         return -1;
1335     }
1336
1337     if (dlt_user.verbose_mode)
1338     {
1339         if ((log->size+sizeof(uint32_t)+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1340         {
1341             return -1;
1342         }
1343
1344         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
1345
1346         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1347         log->size +=sizeof(uint32_t);
1348     }
1349
1350     memcpy((log->buffer)+log->size,&data,sizeof(uint64_t));
1351     log->size += sizeof(uint64_t);
1352
1353     log->args_num ++;
1354
1355     return 0;
1356 }
1357
1358 int dlt_user_log_write_int(DltContextData *log, int data)
1359 {
1360     if (log==0)
1361     {
1362         return -1;
1363     }
1364
1365     switch (sizeof(int))
1366     {
1367     case 1:
1368     {
1369         return dlt_user_log_write_int8(log, (int8_t)data);
1370         break;
1371     }
1372     case 2:
1373     {
1374         return dlt_user_log_write_int16(log, (int16_t)data);
1375         break;
1376     }
1377     case 4:
1378     {
1379         return dlt_user_log_write_int32(log, (int32_t)data);
1380         break;
1381     }
1382     case 8:
1383     {
1384         return dlt_user_log_write_int64(log, (int64_t)data);
1385                 break;
1386     }
1387     default:
1388     {
1389         return -1;
1390         break;
1391     }
1392     }
1393
1394     return 0;
1395 }
1396
1397 int dlt_user_log_write_int8(DltContextData *log, int8_t data)
1398 {
1399     uint32_t type_info;
1400
1401     if (log==0)
1402     {
1403         return -1;
1404     }
1405
1406     if ((log->size+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1407     {
1408         return -1;
1409     }
1410
1411     if (dlt_user.verbose_mode)
1412     {
1413         if ((log->size+sizeof(uint32_t)+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1414         {
1415             return -1;
1416         }
1417
1418         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
1419
1420         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1421         log->size += sizeof(uint32_t);
1422     }
1423
1424     memcpy((log->buffer)+log->size,&data,sizeof(int8_t));
1425     log->size += sizeof(int8_t);
1426
1427     log->args_num ++;
1428
1429     return 0;
1430 }
1431
1432 int dlt_user_log_write_int16(DltContextData *log, int16_t data)
1433 {
1434     uint32_t type_info;
1435
1436     if (log==0)
1437     {
1438         return -1;
1439     }
1440
1441     if ((log->size+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1442     {
1443         return -1;
1444     }
1445
1446     if (dlt_user.verbose_mode)
1447     {
1448         if ((log->size+sizeof(uint32_t)+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1449                 {
1450             return -1;
1451                 }
1452
1453         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
1454
1455         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1456         log->size += sizeof(uint32_t);
1457     }
1458
1459     memcpy((log->buffer)+log->size,&data,sizeof(int16_t));
1460     log->size += sizeof(int16_t);
1461
1462     log->args_num ++;
1463
1464     return 0;
1465 }
1466
1467 int dlt_user_log_write_int32(DltContextData *log, int32_t data)
1468 {
1469     uint32_t type_info;
1470
1471     if (log==0)
1472     {
1473         return -1;
1474     }
1475
1476     if ((log->size+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1477     {
1478         return -1;
1479     }
1480
1481     if (dlt_user.verbose_mode)
1482     {
1483         if ((log->size+sizeof(uint32_t)+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1484         {
1485             return -1;
1486         }
1487
1488         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
1489
1490         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1491         log->size += sizeof(uint32_t);
1492     }
1493
1494     memcpy((log->buffer)+log->size,&data, sizeof(int32_t));
1495     log->size += sizeof(int32_t);
1496
1497     log->args_num ++;
1498
1499     return 0;
1500 }
1501
1502 int dlt_user_log_write_int64(DltContextData *log, int64_t data)
1503 {
1504     uint32_t type_info;
1505
1506     if (log==0)
1507     {
1508         return -1;
1509     }
1510
1511     if ((log->size+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1512     {
1513         return -1;
1514     }
1515
1516     if (dlt_user.verbose_mode)
1517     {
1518         if ((log->size+sizeof(uint32_t)+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1519         {
1520             return -1;
1521         }
1522
1523         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
1524
1525         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1526         log->size += sizeof(uint32_t);
1527     }
1528
1529     memcpy((log->buffer)+log->size,&data,sizeof(int64_t));
1530     log->size += sizeof(int64_t);
1531
1532     log->args_num ++;
1533
1534     return 0;
1535 }
1536
1537 int dlt_user_log_write_bool(DltContextData *log, uint8_t data)
1538 {
1539     uint32_t type_info;
1540
1541     if (log==0)
1542     {
1543         return -1;
1544     }
1545
1546     if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1547     {
1548         return -1;
1549     }
1550
1551     if (dlt_user.verbose_mode)
1552     {
1553         if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1554         {
1555             return -1;
1556         }
1557
1558         type_info = DLT_TYPE_INFO_BOOL;
1559
1560         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1561         log->size += sizeof(uint32_t);
1562     }
1563
1564     memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1565     log->size += sizeof(uint8_t);
1566
1567     log->args_num ++;
1568
1569     return 0;
1570 }
1571
1572 int dlt_user_log_write_string(DltContextData *log, const char *text)
1573 {
1574     uint16_t arg_size;
1575     uint32_t type_info;
1576
1577     if ((log==0) || (text==0))
1578     {
1579         return -1;
1580     }
1581
1582     if ((log->size+(strlen(text)+1)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1583     {
1584         return -1;
1585     }
1586
1587     if (dlt_user.verbose_mode)
1588     {
1589         if ((log->size+(strlen(text)+1)+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1590         {
1591             return -1;
1592         }
1593
1594         type_info = DLT_TYPE_INFO_STRG;
1595
1596         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1597         log->size += sizeof(uint32_t);
1598     }
1599
1600     arg_size = strlen(text) + 1;
1601
1602     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1603     log->size += sizeof(uint16_t);
1604
1605     memcpy((log->buffer)+log->size,text,arg_size);
1606     log->size += arg_size;
1607
1608     log->args_num ++;
1609
1610     return 0;
1611 }
1612
1613 int dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
1614                                     int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length))
1615 {
1616     DltContextData log;
1617     uint32_t i,j,k;
1618     int found = 0;
1619
1620         DltUserInjectionCallback *old;
1621
1622     if (handle==0)
1623     {
1624         return -1;
1625     }
1626
1627     if (dlt_user_log_init(handle, &log)==-1)
1628     {
1629                 return -1;
1630     }
1631
1632     if (service_id<DLT_USER_INJECTION_MIN)
1633     {
1634         return -1;
1635     }
1636     /* This function doesn't make sense storing to local file is choosen;
1637        so terminate this function */
1638     if (dlt_user.dlt_is_file)
1639     {
1640         return 0;
1641     }
1642
1643     DLT_SEM_LOCK();
1644
1645     if (dlt_user.dlt_ll_ts==0)
1646     {
1647         DLT_SEM_FREE();
1648         return 0;
1649     }
1650
1651     /* Insert callback in corresponding table */
1652     i=handle->log_level_pos;
1653
1654     /* Insert each service_id only once */
1655     for (k=0;k<dlt_user.dlt_ll_ts[i].nrcallbacks;k++)
1656     {
1657         if ((dlt_user.dlt_ll_ts[i].injection_table) &&
1658                 (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id))
1659         {
1660             found = 1;
1661             break;
1662         }
1663     }
1664
1665     if (found)
1666     {
1667         j = k;
1668     }
1669     else
1670     {
1671         j=dlt_user.dlt_ll_ts[i].nrcallbacks;
1672
1673         /* Allocate or expand injection table */
1674         if (dlt_user.dlt_ll_ts[i].injection_table == 0)
1675         {
1676             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback));
1677         }
1678         else
1679         {
1680             old = dlt_user.dlt_ll_ts[i].injection_table;
1681             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback)*(j+1));
1682             memcpy(dlt_user.dlt_ll_ts[i].injection_table,old,sizeof(DltUserInjectionCallback)*j);
1683             free(old);
1684         }
1685
1686         dlt_user.dlt_ll_ts[i].nrcallbacks++;
1687     }
1688
1689     /* Store service_id and corresponding function pointer for callback function */
1690     dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id;
1691     dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = dlt_injection_callback;
1692
1693     DLT_SEM_FREE();
1694     return 0;
1695 }
1696
1697 int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
1698 {
1699     DltContextData log;
1700
1701     if (dlt_user_initialised==0)
1702     {
1703         if (dlt_init()<0)
1704         {
1705             return -1;
1706         }
1707     }
1708
1709     if (dlt_user_log_init(handle, &log)==-1)
1710     {
1711                 return -1;
1712     }
1713
1714     if (handle==0)
1715     {
1716         return -1;
1717     }
1718
1719     /* Commented out because of DltNetworkTraceType:
1720
1721     if ((nw_trace_type<=0) || (nw_trace_type>0x15))
1722     {
1723         return -1;
1724     }
1725
1726     */
1727
1728     DLT_SEM_LOCK();
1729
1730     if (dlt_user.dlt_ll_ts==0)
1731     {
1732         DLT_SEM_FREE();
1733         return -1;
1734     }
1735
1736     if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status==DLT_TRACE_STATUS_ON)
1737     {
1738         DLT_SEM_FREE();
1739
1740         log.args_num = 0;
1741         log.trace_status = nw_trace_type;
1742         log.size = 0;
1743
1744         if (header==0)
1745         {
1746             header_len=0;
1747         }
1748
1749         /* Write header and its length */
1750         if (dlt_user_log_write_raw(&log, header, header_len)==-1)
1751         {
1752                 return -1;
1753         }
1754
1755         if (payload==0)
1756         {
1757             payload_len=0;
1758         }
1759
1760         /* Write payload and its length */
1761         if (dlt_user_log_write_raw(&log, payload, payload_len)==-1)
1762         {
1763                         return -1;
1764         }
1765
1766         /* Send log */
1767         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
1768     }
1769     else
1770     {
1771         DLT_SEM_FREE();
1772     }
1773
1774     return 0;
1775 }
1776
1777 int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
1778 {
1779     DltContextData log;
1780
1781     if (dlt_user.verbose_mode==0)
1782     {
1783         return -1;
1784     }
1785
1786     if ((handle==0) || (text==0))
1787     {
1788         return -1;
1789     }
1790
1791     if (dlt_user_log_write_start(handle,&log,loglevel))
1792     {
1793         if (dlt_user_log_write_string(&log,text)==-1)
1794         {
1795                         return -1;
1796         }
1797         if (dlt_user_log_write_finish(&log)==-1)
1798         {
1799                 return -1;
1800         }
1801     }
1802
1803     return 0;
1804 }
1805
1806 int dlt_log_string_int(DltContext *handle,DltLogLevelType loglevel, const char *text, int data)
1807 {
1808     DltContextData log;
1809
1810     if (dlt_user.verbose_mode==0)
1811     {
1812         return -1;
1813     }
1814
1815     if ((handle==0) || (text==0))
1816     {
1817         return -1;
1818     }
1819
1820     if (dlt_user_log_write_start(handle,&log,loglevel))
1821     {
1822         if (dlt_user_log_write_string(&log,text)==-1)
1823         {
1824                         return -1;
1825         }
1826         if (dlt_user_log_write_int(&log,data)==-1)
1827         {
1828                         return -1;
1829         }
1830         if (dlt_user_log_write_finish(&log)==-1)
1831         {
1832                         return -1;
1833         }
1834     }
1835
1836     return 0;
1837 }
1838
1839 int dlt_log_string_uint(DltContext *handle,DltLogLevelType loglevel, const char *text, unsigned int data)
1840 {
1841     DltContextData log;
1842
1843     if (dlt_user.verbose_mode==0)
1844     {
1845         return -1;
1846     }
1847
1848     if ((handle==0) || (text==0))
1849     {
1850         return -1;
1851     }
1852
1853     if (dlt_user_log_write_start(handle,&log,loglevel))
1854     {
1855         if (dlt_user_log_write_string(&log,text)==-1)
1856         {
1857                         return -1;
1858         }
1859         if (dlt_user_log_write_uint(&log,data)==-1)
1860         {
1861                         return -1;
1862         }
1863         if (dlt_user_log_write_finish(&log)==-1)
1864         {
1865                         return -1;
1866         }
1867     }
1868
1869     return 0;
1870 }
1871
1872 int dlt_log_int(DltContext *handle,DltLogLevelType loglevel, int data)
1873 {
1874     DltContextData log;
1875
1876     if (dlt_user.verbose_mode==0)
1877     {
1878         return -1;
1879     }
1880
1881     if (handle==0)
1882     {
1883         return -1;
1884     }
1885
1886     if (dlt_user_log_write_start(handle,&log,loglevel))
1887     {
1888         if (dlt_user_log_write_int(&log,data)==-1)
1889         {
1890                         return -1;
1891         }
1892         if (dlt_user_log_write_finish(&log)==-1)
1893         {
1894                         return -1;
1895         }
1896     }
1897
1898     return 0;
1899 }
1900
1901 int dlt_log_uint(DltContext *handle,DltLogLevelType loglevel, unsigned int data)
1902 {
1903     DltContextData log;
1904
1905     if (dlt_user.verbose_mode==0)
1906     {
1907         return -1;
1908     }
1909
1910     if (handle==0)
1911     {
1912         return -1;
1913     }
1914
1915     if (dlt_user_log_write_start(handle,&log,loglevel))
1916     {
1917         if (dlt_user_log_write_uint(&log,data)==-1)
1918         {
1919                         return -1;
1920         }
1921         if (dlt_user_log_write_finish(&log)==-1)
1922         {
1923                         return -1;
1924         }
1925     }
1926
1927     return 0;
1928 }
1929
1930 int dlt_log_raw(DltContext *handle,DltLogLevelType loglevel, void *data,uint16_t length)
1931 {
1932     DltContextData log;
1933
1934     if (dlt_user.verbose_mode==0)
1935     {
1936         return -1;
1937     }
1938
1939     if (handle==0)
1940     {
1941         return -1;
1942     }
1943
1944     if (dlt_user_log_write_start(handle,&log,loglevel))
1945     {
1946         if (dlt_user_log_write_raw(&log,data,length)==-1)
1947         {
1948                         return -1;
1949         }
1950         if (dlt_user_log_write_finish(&log)==-1)
1951         {
1952                         return -1;
1953         }
1954     }
1955
1956     return 0;
1957 }
1958
1959 int dlt_verbose_mode(void)
1960 {
1961     if (dlt_user_initialised==0)
1962     {
1963         if (dlt_init()<0)
1964         {
1965             return -1;
1966         }
1967     }
1968
1969     /* Switch to verbose mode */
1970     dlt_user.verbose_mode = 1;
1971
1972     return 0;
1973 }
1974
1975 int dlt_nonverbose_mode(void)
1976 {
1977     if (dlt_user_initialised==0)
1978     {
1979         if (dlt_init()<0)
1980         {
1981             return -1;
1982         }
1983     }
1984
1985     /* Switch to non-verbose mode */
1986     dlt_user.verbose_mode = 0;
1987
1988     return 0;
1989 }
1990
1991 int dlt_enable_local_print(void)
1992 {
1993     if (dlt_user_initialised==0)
1994     {
1995         if (dlt_init()<0)
1996         {
1997             return -1;
1998         }
1999     }
2000
2001     dlt_user.enable_local_print = 1;
2002
2003     return 0;
2004 }
2005
2006 int dlt_disable_local_print(void)
2007 {
2008     if (dlt_user_initialised==0)
2009     {
2010         if (dlt_init()<0)
2011         {
2012             return -1;
2013         }
2014     }
2015
2016     dlt_user.enable_local_print = 0;
2017
2018     return 0;
2019 }
2020
2021 void dlt_user_receiverthread_function(void *ptr)
2022 {
2023     while (1)
2024     {
2025         /* Check for new messages from DLT daemon */
2026         if (dlt_user_log_check_user_message()==-1)
2027         {
2028                         /* Critical error */
2029                         dlt_log(LOG_CRIT,"Receiver thread encountered error condition\n");
2030         }
2031
2032         usleep(DLT_USER_RECEIVE_DELAY); /* delay */
2033     }
2034 }
2035
2036 /* Private functions of user library */
2037
2038 int dlt_user_log_init(DltContext *handle, DltContextData *log)
2039 {
2040     if (dlt_user_initialised==0)
2041     {
2042         if (dlt_init()<0)
2043         {
2044             return -1;
2045         }
2046     }
2047
2048     log->handle = handle;
2049
2050     return 0;
2051 }
2052
2053 int dlt_user_log_send_log(DltContextData *log, int mtype)
2054 {
2055     DltMessage msg;
2056     DltUserHeader userheader;
2057     int32_t len;
2058
2059     DltReturnValue ret = 0;
2060
2061     if (log==0)
2062     {
2063         return -1;
2064     }
2065
2066     if (log->handle==0)
2067     {
2068         return -1;
2069     }
2070
2071     if (dlt_user.appID[0]=='\0')
2072     {
2073         return -1;
2074     }
2075
2076     if (log->handle->contextID[0]=='\0')
2077     {
2078         return -1;
2079     }
2080
2081     if ((mtype<DLT_TYPE_LOG) || (mtype>DLT_TYPE_CONTROL))
2082     {
2083         return -1;
2084     }
2085
2086     /* also for Trace messages */
2087 #ifdef DLT_SHM_ENABLE
2088     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_SHM)==-1)
2089 #else
2090     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
2091 #endif
2092     {
2093                 return -1;
2094     }
2095
2096     if (dlt_message_init(&msg,0)==-1)
2097     {
2098         return -1;
2099     }
2100
2101     msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
2102
2103     if (dlt_set_storageheader(msg.storageheader,dlt_user.ecuID)==-1)
2104     {
2105                 return -1;
2106     }
2107
2108     msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
2109     msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_PROTOCOL_VERSION1 ;
2110
2111     if (dlt_user.verbose_mode)
2112     {
2113         /* In verbose mode, send extended header */
2114         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2115     }
2116     else
2117     {
2118         /* In non-verbose, send extended header if desired */
2119 #if (DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE==1)
2120         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2121 #endif
2122     }
2123
2124 #if (BYTE_ORDER==BIG_ENDIAN)
2125     msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
2126 #endif
2127
2128     msg.standardheader->mcnt = log->handle->mcnt++;
2129
2130     /* Set header extra parameters */
2131     dlt_set_id(msg.headerextra.ecu,dlt_user.ecuID);
2132     //msg.headerextra.seid = 0;
2133     msg.headerextra.tmsp = dlt_uptime();
2134
2135     if (dlt_message_set_extraparameters(&msg,0)==-1)
2136     {
2137         return -1;
2138     }
2139
2140     /* Fill out extended header, if extended header should be provided */
2141     if (DLT_IS_HTYP_UEH(msg.standardheader->htyp))
2142     {
2143         /* with extended header */
2144         msg.extendedheader = (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)  );
2145
2146         switch (mtype)
2147         {
2148         case DLT_TYPE_LOG:
2149         {
2150             msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2151             break;
2152         }
2153         case DLT_TYPE_NW_TRACE:
2154         {
2155             msg.extendedheader->msin = (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT) | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2156             break;
2157         }
2158         default:
2159         {
2160                     /* This case should not occur */
2161             return -1;
2162             break;
2163         }
2164         }
2165
2166         /* If in verbose mode, set flag in header for verbose mode */
2167         if (dlt_user.verbose_mode)
2168         {
2169             msg.extendedheader->msin |= DLT_MSIN_VERB;
2170         }
2171
2172         msg.extendedheader->noar = log->args_num;              /* number of arguments */
2173         dlt_set_id(msg.extendedheader->apid,dlt_user.appID);       /* application id */
2174         dlt_set_id(msg.extendedheader->ctid,log->handle->contextID);   /* context id */
2175
2176         msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2177     }
2178     else
2179     {
2180         /* without extended header */
2181         msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2182     }
2183
2184     len=msg.headersize - sizeof(DltStorageHeader) +log->size;
2185     if (len>UINT16_MAX)
2186     {
2187         dlt_log(LOG_CRIT,"Huge message discarded!\n");
2188         return -1;
2189     }
2190
2191     msg.standardheader->len = DLT_HTOBE_16(len);
2192
2193     /* print to std out, if enabled */
2194     if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) &&
2195             (dlt_user.local_print_mode != DLT_PM_AUTOMATIC))
2196     {
2197         if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
2198         {
2199             if (dlt_user_print_msg(&msg, log)==-1)
2200             {
2201                                 return -1;
2202             }
2203         }
2204     }
2205
2206     if (dlt_user.dlt_is_file)
2207     {
2208         /* log to file */
2209         ret=dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size);
2210         return ((ret==DLT_RETURN_OK)?0:-1);
2211     }
2212     else
2213     {
2214         /* Reattach to daemon if neccesary */
2215         dlt_user_log_reattach_to_daemon();
2216
2217         if (dlt_user.overflow)
2218         {
2219             if (dlt_user_log_send_overflow()==0)
2220             {
2221                 dlt_user.overflow=0;
2222             }
2223         }
2224
2225                 /* try to resent old data first */
2226                 ret = 0;
2227                 if(dlt_user.dlt_log_handle!=-1)
2228                         ret = dlt_user_log_resend_buffer();
2229                 if(ret==0) 
2230                 {
2231                         /* resend ok or nothing to resent */
2232 #ifdef DLT_SHM_ENABLE
2233                         if(dlt_user.dlt_log_handle!=-1)
2234                                 dlt_shm_push(&dlt_user.dlt_shm,msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
2235                                                                                         log->buffer, log->size,0,0);                   
2236
2237                         /* log to FIFO */
2238                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
2239                                                                         &(userheader), sizeof(DltUserHeader),
2240                                                                         0, 0,
2241                                                                         0, 0);
2242 #else
2243                         /* log to FIFO */
2244 #ifdef DLT_TEST_ENABLE
2245                         if(dlt_user.corrupt_user_header) {
2246                                 userheader.pattern[0]=0xff;
2247                                 userheader.pattern[1]=0xff;
2248                                 userheader.pattern[2]=0xff;
2249                                 userheader.pattern[3]=0xff;
2250                         }
2251                         if(dlt_user.corrupt_message_size) {
2252                                 msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
2253                         }
2254 #endif
2255                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
2256                                                                         &(userheader), sizeof(DltUserHeader),
2257                                                                         msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
2258                                                                         log->buffer, log->size);                
2259 #endif                  
2260                 }
2261                 
2262         /* store message in ringbuffer, if an error has occured */
2263         if (ret!=DLT_RETURN_OK)
2264         {
2265             DLT_SEM_LOCK();
2266
2267             if (dlt_buffer_push3(&(dlt_user.startup_buffer),
2268                                 (unsigned char *)&(userheader), sizeof(DltUserHeader),
2269                                 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
2270                                 log->buffer, log->size)==-1)
2271                         {
2272                                 dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
2273                         }
2274
2275             DLT_SEM_FREE();
2276         }
2277
2278         switch (ret)
2279         {
2280         case DLT_RETURN_PIPE_FULL:
2281         {
2282             /* data could not be written */
2283             dlt_user.overflow = 1;
2284             return -1;
2285         }
2286         case DLT_RETURN_PIPE_ERROR:
2287         {
2288             /* handle not open or pipe error */
2289             close(dlt_user.dlt_log_handle);
2290             dlt_user.dlt_log_handle = -1;
2291
2292 #ifdef DLT_SHM_ENABLE
2293                         /* free shared memory */
2294                         dlt_shm_free_client(&dlt_user.dlt_shm);
2295 #endif
2296
2297             if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
2298             {
2299                 dlt_user_print_msg(&msg, log);
2300             }
2301
2302             return -1;
2303         }
2304         case DLT_RETURN_ERROR:
2305         {
2306             /* other error condition */
2307             return -1;
2308         }
2309                 case DLT_RETURN_OK:
2310         {
2311                 return 0;
2312         }
2313                 default:
2314                 {
2315                         /* This case should never occur. */
2316                         return -1;
2317                 }
2318         }
2319     }
2320
2321     return 0;
2322 }
2323
2324 int dlt_user_log_send_register_application(void)
2325 {
2326     DltUserHeader userheader;
2327     DltUserControlMsgRegisterApplication usercontext;
2328
2329     DltReturnValue ret;
2330
2331     if (dlt_user.appID[0]=='\0')
2332     {
2333         return -1;
2334     }
2335
2336     /* set userheader */
2337     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION)==-1)
2338     {
2339                 return -1;
2340     }
2341
2342     /* set usercontext */
2343     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
2344     usercontext.pid = getpid();
2345
2346     if (dlt_user.application_description!=0)
2347     {
2348         usercontext.description_length = strlen(dlt_user.application_description);
2349     }
2350     else
2351     {
2352         usercontext.description_length = 0;
2353     }
2354
2355     if (dlt_user.dlt_is_file)
2356     {
2357         return 0;
2358     }
2359
2360     /* log to FIFO */
2361     ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication),dlt_user.application_description,usercontext.description_length);
2362         return ((ret==DLT_RETURN_OK)?0:-1);
2363 }
2364
2365 int dlt_user_log_send_unregister_application(void)
2366 {
2367     DltUserHeader userheader;
2368     DltUserControlMsgUnregisterApplication usercontext;
2369
2370     DltReturnValue ret;
2371
2372     if (dlt_user.appID[0]=='\0')
2373     {
2374         return -1;
2375     }
2376
2377     /* set userheader */
2378     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION)==-1)
2379     {
2380         return -1;
2381     }
2382
2383     /* set usercontext */
2384     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
2385     usercontext.pid = getpid();
2386
2387     if (dlt_user.dlt_is_file)
2388     {
2389         return 0;
2390     }
2391
2392     /* log to FIFO */
2393     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication));
2394     return ((ret==DLT_RETURN_OK)?0:-1);
2395 }
2396
2397 int dlt_user_log_send_register_context(DltContextData *log)
2398 {
2399     DltUserHeader userheader;
2400     DltUserControlMsgRegisterContext usercontext;
2401     DltReturnValue ret;
2402
2403     if (log==0)
2404     {
2405                 return -1;
2406     }
2407
2408     if (log->handle==0)
2409     {
2410         return -1;
2411     }
2412
2413     if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
2414     {
2415         return -1;
2416     }
2417
2418     /* set userheader */
2419     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT)==-1)
2420     {
2421                 return -1;
2422     }
2423
2424     /* set usercontext */
2425     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
2426     dlt_set_id(usercontext.ctid,log->handle->contextID);       /* context id */
2427     usercontext.log_level_pos = log->handle->log_level_pos;
2428     usercontext.pid = getpid();
2429
2430     usercontext.log_level = (int8_t)log->log_level;
2431     usercontext.trace_status = (int8_t)log->trace_status;
2432
2433     if (log->context_description!=0)
2434     {
2435         usercontext.description_length = strlen(log->context_description);
2436     }
2437     else
2438     {
2439                 usercontext.description_length = 0;
2440     }
2441
2442     if (dlt_user.dlt_is_file)
2443     {
2444         return 0;
2445     }
2446
2447     /* log to FIFO */
2448     ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext),log->context_description,usercontext.description_length);
2449     return ((ret==DLT_RETURN_OK)?0:-1);
2450 }
2451
2452 int dlt_user_log_send_unregister_context(DltContextData *log)
2453 {
2454     DltUserHeader userheader;
2455     DltUserControlMsgUnregisterContext usercontext;
2456     DltReturnValue ret;
2457
2458     if (log==0)
2459     {
2460         return -1;
2461     }
2462
2463     if (log->handle==0)
2464     {
2465         return -1;
2466     }
2467
2468     if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
2469     {
2470         return -1;
2471     }
2472
2473     /* set userheader */
2474     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT)==-1)
2475     {
2476                 return -1;
2477     }
2478
2479     /* set usercontext */
2480     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
2481     dlt_set_id(usercontext.ctid,log->handle->contextID);       /* context id */
2482     usercontext.pid = getpid();
2483
2484     if (dlt_user.dlt_is_file)
2485     {
2486         return 0;
2487     }
2488
2489     /* log to FIFO */
2490     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext));
2491         return ((ret==DLT_RETURN_OK)?0:-1);
2492 }
2493
2494 int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
2495 {
2496     DltUserHeader userheader;
2497     DltUserControlMsgAppLogLevelTraceStatus usercontext;
2498         DltReturnValue ret;
2499
2500     if ((appid==0) || (appid[0]=='\0'))
2501     {
2502         return -1;
2503     }
2504
2505     /* Removed because of DltLogLevelType and DltTraceStatusType
2506
2507     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
2508     {
2509         return -1;
2510     }
2511
2512     if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
2513     {
2514         return -1;
2515     }
2516
2517     */
2518
2519     /* set userheader */
2520     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS)==-1)
2521     {
2522                 return -1;
2523     }
2524
2525     /* set usercontext */
2526     dlt_set_id(usercontext.apid,appid);       /* application id */
2527     usercontext.log_level = loglevel;
2528     usercontext.trace_status = tracestatus;
2529
2530     if (dlt_user.dlt_is_file)
2531     {
2532         return 0;
2533     }
2534
2535     /* log to FIFO */
2536     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus));
2537     return ((ret==DLT_RETURN_OK)?0:-1);
2538 }
2539
2540 int dlt_user_log_send_log_mode(DltUserLogMode mode)
2541 {
2542     DltUserHeader userheader;
2543     DltUserControlMsgLogMode logmode;
2544
2545     DltReturnValue ret;
2546
2547     /* set userheader */
2548     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE)==-1)
2549     {
2550         return -1;
2551     }
2552
2553     /* set data */
2554     logmode.log_mode = (unsigned char) mode;
2555
2556     if (dlt_user.dlt_is_file)
2557     {
2558         return 0;
2559     }
2560
2561     /* log to FIFO */
2562     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode));
2563     return ((ret==DLT_RETURN_OK)?0:-1);
2564 }
2565
2566 int dlt_user_print_msg(DltMessage *msg, DltContextData *log)
2567 {
2568     uint8_t *databuffer_tmp;
2569     int32_t datasize_tmp;
2570     static char text[DLT_USER_TEXT_LENGTH];
2571
2572     if ((msg==0) || (log==0))
2573     {
2574         return -1;
2575     }
2576
2577     /* Save variables before print */
2578     databuffer_tmp = msg->databuffer;
2579     datasize_tmp = msg->datasize;
2580
2581     /* Act like a receiver, convert header back to host format */
2582     msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len);
2583     dlt_message_get_extraparameters(msg,0);
2584
2585     msg->databuffer = log->buffer;
2586     msg->datasize = log->size;
2587
2588     /* Print message as ASCII */
2589     if (dlt_message_print_ascii(msg,text,DLT_USER_TEXT_LENGTH,0)==-1)
2590     {
2591                 return -1;
2592     }
2593
2594     /* Restore variables and set len to BE*/
2595     msg->databuffer = databuffer_tmp;
2596     msg->datasize =  datasize_tmp;
2597
2598     msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
2599
2600     return 0;
2601 }
2602
2603 int dlt_user_log_check_user_message(void)
2604 {
2605     int offset=0;
2606     int leave_while=0;
2607
2608     uint32_t i;
2609
2610     DltUserHeader *userheader;
2611     DltReceiver *receiver = &(dlt_user.receiver);
2612
2613     DltUserControlMsgLogLevel *usercontextll;
2614     DltUserControlMsgInjection *usercontextinj;
2615     DltUserControlMsgLogState *userlogstate;
2616     unsigned char *userbuffer;
2617     unsigned char *inject_buffer;
2618
2619     if (dlt_user.dlt_user_handle!=-1)
2620     {
2621         while (1)
2622         {
2623             if (dlt_receiver_receive_fd(receiver)<=0)
2624             {
2625                 /* No new message available */
2626                 return 0;
2627             }
2628
2629             /* look through buffer as long as data is in there */
2630             while (1)
2631             {
2632                 if (receiver->bytesRcvd < (int32_t)sizeof(DltUserHeader))
2633                 {
2634                     break;
2635                 }
2636
2637                 /* resync if necessary */
2638                 offset=0;
2639                 do
2640                 {
2641                     userheader = (DltUserHeader*) (receiver->buf+offset);
2642
2643                     /* Check for user header pattern */
2644                     if (dlt_user_check_userheader(userheader))
2645                     {
2646                         break;
2647                     }
2648                     offset++;
2649
2650                 }
2651                 while ((int32_t)(sizeof(DltUserHeader)+offset)<=receiver->bytesRcvd);
2652
2653                 /* Check for user header pattern */
2654                 if (dlt_user_check_userheader(userheader)==0)
2655                 {
2656                     break;
2657                 }
2658
2659                 /* Set new start offset */
2660                 if (offset>0)
2661                 {
2662                     receiver->buf+=offset;
2663                     receiver->bytesRcvd-=offset;
2664                 }
2665
2666                 switch (userheader->message)
2667                 {
2668                 case DLT_USER_MESSAGE_LOG_LEVEL:
2669                 {
2670                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel)))
2671                     {
2672                         leave_while=1;
2673                         break;
2674                     }
2675
2676                     usercontextll = (DltUserControlMsgLogLevel*) (receiver->buf+sizeof(DltUserHeader));
2677
2678                     /* Update log level and trace status */
2679                     if (usercontextll!=0)
2680                     {
2681                         DLT_SEM_LOCK();
2682
2683                         if ((usercontextll->log_level_pos >= 0) && (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries))
2684                         {
2685                             // printf("Store ll, ts\n");
2686                             if (dlt_user.dlt_ll_ts)
2687                             {
2688                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = usercontextll->log_level;
2689                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status = usercontextll->trace_status;
2690                             }
2691                         }
2692
2693                         DLT_SEM_FREE();
2694                     }
2695
2696                     /* keep not read data in buffer */
2697                     if (dlt_receiver_remove(receiver,sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel))==-1)
2698                     {
2699                         return -1;
2700                     }
2701                 }
2702                 break;
2703                 case DLT_USER_MESSAGE_INJECTION:
2704                 {
2705                     /* At least, user header, user context, and service id and data_length of injected message is available */
2706                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)))
2707                     {
2708                         leave_while = 1;
2709                         break;
2710                     }
2711
2712                     usercontextinj = (DltUserControlMsgInjection*) (receiver->buf+sizeof(DltUserHeader));
2713                     userbuffer = (unsigned char*) (receiver->buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection));
2714                     inject_buffer = 0;
2715
2716                     if (userbuffer!=0)
2717                     {
2718
2719                         if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))
2720                         {
2721                             leave_while = 1;
2722                             break;
2723                         }
2724
2725                         DLT_SEM_LOCK();
2726
2727                         if ((usercontextinj->data_length_inject>0) && (dlt_user.dlt_ll_ts))
2728                         {
2729                             /* Check if injection callback is registered for this context */
2730                             for (i=0; i<dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks;i++)
2731                             {
2732                                 if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) &&
2733                                         (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id == usercontextinj->service_id))
2734                                 {
2735                                     /* callback available, so prepare data, then call it */
2736                                     inject_buffer = malloc(usercontextinj->data_length_inject);
2737                                     if (inject_buffer!=0)
2738                                     {
2739                                         /* copy from receiver to inject_buffer */
2740                                         memcpy(inject_buffer, userbuffer, usercontextinj->data_length_inject);
2741
2742                                         /* call callback */
2743                                         if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback!=0)
2744                                         {
2745                                             // printf("Got injection(%d), length=%d, '%s' \n", usercontext->service_id, usercontext->data_length_inject, inject_buffer);
2746                                             dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback(
2747                                                 usercontextinj->service_id, inject_buffer, usercontextinj->data_length_inject);
2748                                         }
2749
2750                                         if (inject_buffer!=0)
2751                                         {
2752                                             free(inject_buffer);
2753                                             inject_buffer = 0;
2754                                         }
2755                                     }
2756
2757                                     break;
2758                                 }
2759                             }
2760                         }
2761
2762                         DLT_SEM_FREE();
2763
2764                         /* keep not read data in buffer */
2765                         if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))==-1)
2766                                                 {
2767                                                         return -1;
2768                                                 }
2769                     }
2770                 }
2771                 break;
2772                 case DLT_USER_MESSAGE_LOG_STATE:
2773                 {
2774                     /* At least, user header, user context, and service id and data_length of injected message is available */
2775                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))
2776                     {
2777                         leave_while = 1;
2778                         break;
2779                     }
2780
2781                     userlogstate = (DltUserControlMsgLogState*) (receiver->buf+sizeof(DltUserHeader));
2782                                         dlt_user.log_state = userlogstate->log_state;
2783
2784                                         /* keep not read data in buffer */
2785                                         if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))==-1)
2786                                         {
2787                                                 return -1;
2788                                         }
2789                 }
2790                 break;
2791                 default:
2792                 {
2793                     dlt_log(LOG_ERR,"Invalid user message type received!\n");
2794                     /* Ignore result */
2795                     dlt_receiver_remove(receiver,sizeof(DltUserHeader));
2796                                         /* In next invocation of while loop, a resync will be triggered if additional data was received */
2797                 }
2798                 break;
2799                 } /* switch() */
2800
2801                 if (leave_while==1)
2802                 {
2803                     leave_while=0;
2804                     break;
2805                 }
2806
2807             } /* while buffer*/
2808
2809             if (dlt_receiver_move_to_begin(receiver)==-1)
2810             {
2811                                 return -1;
2812             }
2813         } /* while receive */
2814     } /* if */
2815
2816     return DLT_RETURN_OK;
2817 }
2818
2819 int dlt_user_log_resend_buffer(void)
2820 {
2821         int num,count;
2822     uint8_t buf[DLT_USER_RCVBUF_MAX_SIZE];
2823     int size;
2824         DltReturnValue ret;
2825         
2826         /* Send content of ringbuffer */
2827         DLT_SEM_LOCK();
2828         count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
2829         DLT_SEM_FREE();
2830
2831         for (num=0;num<count;num++)
2832         {
2833
2834                 DLT_SEM_LOCK();
2835                 size = dlt_buffer_copy(&(dlt_user.startup_buffer),buf,sizeof(buf));
2836
2837                 if (size>0)
2838                 {
2839 #ifdef DLT_SHM_ENABLE                                           
2840                         dlt_shm_push(&dlt_user.dlt_shm,buf+sizeof(DltUserHeader),size-sizeof(DltUserHeader),0,0,0,0);                   
2841
2842                         /* log to FIFO */
2843                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle, buf,sizeof(DltUserHeader),0,0,0,0);
2844 #else
2845                         /* log to FIFO */
2846                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle, buf,size,0,0,0,0);
2847 #endif
2848
2849                         /* in case of error, keep message in ringbuffer */                        
2850                         if (ret==DLT_RETURN_OK)
2851                         {
2852                                 dlt_buffer_remove(&(dlt_user.startup_buffer));
2853                                 /*
2854                                 DLT_SEM_LOCK();
2855                                 if (dlt_buffer_push(&(dlt_user.startup_buffer), buf, size)==-1)
2856                                 {
2857                                         dlt_log(LOG_ERR,"Error pushing back message to history buffer. Message discarded.\n");
2858                                 }
2859                                 DLT_SEM_FREE();
2860
2861                                 // In case of: data could not be written, set overflow flag
2862                                 if (ret==DLT_RETURN_PIPE_FULL)
2863                                 {
2864                                         dlt_user.overflow = 1;
2865                                 }
2866                                 */
2867                         }
2868                         else
2869                         {
2870                                 /* keep message in ringbuffer */   
2871                                 DLT_SEM_FREE();
2872                                 return -1;
2873                         }
2874                 }
2875                 DLT_SEM_FREE();
2876         }
2877         
2878         return 0;
2879 }
2880
2881 void dlt_user_log_reattach_to_daemon(void)
2882 {
2883         uint32_t num,reregistered=0;
2884
2885         DltContext handle;
2886         DltContextData log_new;
2887
2888     if (dlt_user.dlt_log_handle<0)
2889     {
2890         dlt_user.dlt_log_handle=-1;
2891
2892         /* try to open pipe to dlt daemon */
2893         dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK);
2894         if (dlt_user.dlt_log_handle > 0)
2895         {
2896             if (dlt_user_log_init(&handle,&log_new)==-1)
2897             {
2898                 return;
2899             }
2900
2901 #ifdef DLT_SHM_ENABLE
2902                         /* init shared memory */
2903                         if (dlt_shm_init_client(&dlt_user.dlt_shm,DLT_SHM_KEY) < 0)
2904                         {
2905                                 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
2906                                 dlt_log(LOG_WARNING, str);
2907                                 //return 0; 
2908                         }   
2909 #endif
2910
2911             dlt_log(LOG_NOTICE, "Logging re-enabled!\n");
2912
2913             /* Re-register application */
2914             if (dlt_user_log_send_register_application()==-1)
2915             {
2916                 return;
2917             }
2918
2919             DLT_SEM_LOCK();
2920
2921             /* Re-register all stored contexts */
2922             for (num=0; num<dlt_user.dlt_ll_ts_num_entries; num++)
2923             {
2924                 /* Re-register stored context */
2925                 if ((dlt_user.appID[0]!='\0') && (dlt_user.dlt_ll_ts[num].contextID[0]!='\0') && (dlt_user.dlt_ll_ts))
2926                 {
2927                     //dlt_set_id(log_new.appID, dlt_user.appID);
2928                     dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
2929                     handle.log_level_pos = num;
2930                     log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
2931
2932                     log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
2933                     log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
2934
2935                     if (dlt_user_log_send_register_context(&log_new)==-1)
2936                     {
2937                         DLT_SEM_FREE();
2938                         return;
2939                     }
2940
2941                     reregistered=1;
2942                 }
2943             }
2944
2945             DLT_SEM_FREE();
2946
2947             if (reregistered==1)
2948             {
2949                                 dlt_user_log_resend_buffer();
2950             }
2951         }
2952     }
2953 }
2954
2955 int dlt_user_log_send_overflow(void)
2956 {
2957     DltUserHeader userheader;
2958     DltReturnValue ret;
2959
2960     /* set userheader */
2961     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW)==-1)
2962     {
2963         return -1;
2964     }
2965
2966     if (dlt_user.dlt_is_file)
2967     {
2968         return 0;
2969     }
2970
2971     /* log to FIFO */
2972     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), 0, 0);
2973     return ((ret==DLT_RETURN_OK)?0:-1);
2974 }
2975
2976 int dlt_user_check_buffer(int *total_size, int *used_size)
2977 {
2978 #ifdef DLT_SHM_ENABLE
2979         *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm));
2980         *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm));
2981 #else
2982         *total_size = dlt_buffer_get_total_size(&(dlt_user.startup_buffer));
2983         *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer));
2984 #endif
2985         
2986         return 0; /* ok */
2987 }
2988
2989 #ifdef DLT_TEST_ENABLE
2990 void dlt_user_test_corrupt_user_header(int enable)
2991 {
2992     dlt_user.corrupt_user_header = enable;
2993 }
2994 void dlt_user_test_corrupt_message_size(int enable,int16_t size)
2995 {
2996     dlt_user.corrupt_message_size = enable;
2997     dlt_user.corrupt_message_size_size = size;
2998 }
2999 #endif
3000
3001