33bab2c61122885df6de16f00a082d18180af375
[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.wenzel@bmw.de> BMW 2011-2012
17  *
18  * \file <FILE>
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             dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description = malloc(strlen(description)+1);
671             strncpy(dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description, description, strlen(description));
672
673             /* Terminate transmitted string with 0 */
674             dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description[strlen(description)]='\0';
675         }
676
677         if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
678         {
679             dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].log_level = loglevel;
680         }
681
682         if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
683         {
684             dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].trace_status = tracestatus;
685         }
686
687         /* Prepare transfer struct */
688         //dlt_set_id(log->appID, dlt_user.appID);
689         dlt_set_id(handle->contextID, contextid);
690         handle->log_level_pos = dlt_user.dlt_ll_ts_num_entries;
691
692         log.context_description = dlt_user.dlt_ll_ts[dlt_user.dlt_ll_ts_num_entries].context_description;
693
694         if (loglevel!=DLT_USER_LOG_LEVEL_NOT_SET)
695         {
696             log.log_level = loglevel;
697         }
698         else
699         {
700             log.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
701         }
702
703         if (tracestatus!=DLT_USER_TRACE_STATUS_NOT_SET)
704         {
705             log.trace_status = tracestatus;
706         }
707         else
708         {
709             log.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
710         }
711
712         dlt_user.dlt_ll_ts_num_entries++;
713
714         DLT_SEM_FREE();
715
716         ret=dlt_user_log_send_register_context(&log);
717     }
718     else
719     {
720         DLT_SEM_FREE();
721
722         ret=-1;
723     }
724
725     return ret;
726 }
727
728 int dlt_unregister_app(void)
729 {
730     int ret;
731
732     if (dlt_user_initialised==0)
733     {
734         return -1;
735     }
736
737     /* Inform daemon to unregister application and all of its contexts */
738     ret = dlt_user_log_send_unregister_application();
739
740     DLT_SEM_LOCK();
741
742     /* Clear and free local stored application information */
743     dlt_set_id(dlt_user.appID, "");
744
745     if (dlt_user.application_description!=0)
746     {
747         free(dlt_user.application_description);
748     }
749
750     dlt_user.application_description = 0;
751
752     DLT_SEM_FREE();
753
754     return ret;
755 }
756
757 int dlt_unregister_context(DltContext *handle)
758 {
759     DltContextData log;
760     int ret;
761
762     if (dlt_user_initialised==0)
763     {
764         return -1;
765     }
766
767     if (dlt_user_log_init(handle, &log) == -1)
768     {
769                 return -1;
770     }
771
772     DLT_SEM_LOCK();
773
774     if (dlt_user.dlt_ll_ts)
775     {
776         /* Clear and free local stored context information */
777         dlt_set_id(dlt_user.dlt_ll_ts[handle->log_level_pos].contextID, "");
778
779         dlt_user.dlt_ll_ts[handle->log_level_pos].log_level = DLT_USER_INITIAL_LOG_LEVEL;
780         dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status = DLT_USER_INITIAL_TRACE_STATUS;
781
782         if (dlt_user.dlt_ll_ts[handle->log_level_pos].context_description!=0)
783         {
784             free(dlt_user.dlt_ll_ts[handle->log_level_pos].context_description);
785         }
786
787         dlt_user.dlt_ll_ts[handle->log_level_pos].context_description = 0;
788
789         if (dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table)
790         {
791             free(dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table);
792             dlt_user.dlt_ll_ts[handle->log_level_pos].injection_table = 0;
793         }
794
795         dlt_user.dlt_ll_ts[handle->log_level_pos].nrcallbacks     = 0;
796     }
797
798     DLT_SEM_FREE();
799
800     /* Inform daemon to unregister context */
801     ret = dlt_user_log_send_unregister_context(&log);
802
803     return ret;
804 }
805
806 int dlt_set_application_ll_ts_limit(DltLogLevelType loglevel, DltTraceStatusType tracestatus)
807 {
808     uint32_t i;
809     int ret;
810
811     if (dlt_user_initialised==0)
812     {
813         if (dlt_init()<0)
814         {
815             return -1;
816         }
817     }
818
819     /* Removed because of DltLogLevelType and DltTraceStatusType
820
821     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
822     {
823         return -1;
824     }
825
826     if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
827     {
828         return -1;
829     }
830
831     if (dlt_user.dlt_ll_ts==0)
832     {
833         return -1;
834     }
835
836     */
837
838     DLT_SEM_LOCK();
839
840     /* Update local structures */
841     for (i=0; i<dlt_user.dlt_ll_ts_num_entries;i++)
842     {
843         dlt_user.dlt_ll_ts[i].log_level = loglevel;
844         dlt_user.dlt_ll_ts[i].trace_status = tracestatus;
845     }
846
847     DLT_SEM_FREE();
848
849     /* Inform DLT server about update */
850     ret = dlt_send_app_ll_ts_limit(dlt_user.appID, loglevel, tracestatus);
851
852     return ret;
853 }
854
855 int dlt_get_log_state()
856 {
857         return dlt_user.log_state;
858 }
859
860 int dlt_set_log_mode(DltUserLogMode mode)
861 {
862     if (dlt_user_initialised==0)
863     {
864         if (dlt_init()<0)
865         {
866             return -1;
867         }
868     }
869
870         return dlt_user_log_send_log_mode(mode);
871 }
872
873 int dlt_forward_msg(void *msgdata,size_t size)
874 {
875     DltUserHeader userheader;
876     DltReturnValue ret;
877
878     if ((msgdata==0) || (size==0))
879     {
880         return -1;
881     }
882
883     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
884     {
885         /* Type of internal user message; same value for Trace messages */
886         return -1;
887     }
888
889     if (dlt_user.dlt_is_file)
890     {
891         /* log to file */
892         ret = dlt_user_log_out2(dlt_user.dlt_log_handle, msgdata, size, 0, 0);
893         return ((ret==DLT_RETURN_OK)?0:-1);
894     }
895     else
896     {
897         /* Reattach to daemon if neccesary */
898         dlt_user_log_reattach_to_daemon();
899
900         if (dlt_user.overflow)
901         {
902             if (dlt_user_log_send_overflow()==0)
903             {
904                 dlt_user.overflow=0;
905             }
906         }
907
908         /* log to FIFO */
909         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
910                                 &(userheader), sizeof(DltUserHeader),
911                                 msgdata, size, 0, 0);
912
913         /* store message in ringbuffer, if an error has occured */
914         if (ret!=DLT_RETURN_OK)
915         {
916             DLT_SEM_LOCK();
917
918             if (dlt_buffer_push3(&(dlt_user.startup_buffer),
919                                 (unsigned char *)&(userheader), sizeof(DltUserHeader),
920                                  msgdata, size, 0, 0)==-1)
921                         {
922                                 dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
923                         }
924
925             DLT_SEM_FREE();
926         }
927
928         switch (ret)
929         {
930         case DLT_RETURN_PIPE_FULL:
931         {
932             /* data could not be written */
933             dlt_user.overflow = 1;
934             return -1;
935         }
936         case DLT_RETURN_PIPE_ERROR:
937         {
938             /* handle not open or pipe error */
939             close(dlt_user.dlt_log_handle);
940             dlt_user.dlt_log_handle = -1;
941
942             return -1;
943         }
944         case DLT_RETURN_ERROR:
945         {
946             /* other error condition */
947             return -1;
948         }
949         case DLT_RETURN_OK:
950         {
951                 return 0;
952         }
953                 default:
954                 {
955                         /* This case should not occur */
956                         return -1;
957                 }
958         }
959     }
960
961     return 0;
962 }
963
964 /* ********************************************************************************************* */
965
966 int dlt_user_log_write_start(DltContext *handle, DltContextData *log,DltLogLevelType loglevel)
967 {
968     return dlt_user_log_write_start_id(handle,log,loglevel,DLT_USER_DEFAULT_MSGID);
969 }
970
971 int dlt_user_log_write_start_id(DltContext *handle, DltContextData *log,DltLogLevelType loglevel, uint32_t messageid)
972 {
973     uint32_t mid;
974
975     if (dlt_user_initialised==0)
976     {
977         if (dlt_init()<0)
978         {
979             return -1;
980         }
981     }
982
983     if (dlt_user_log_init(handle, log)==-1)
984     {
985                 return -1;
986     }
987
988     if (log==0)
989     {
990         return -1;
991     }
992
993     /* Removed because of DltLogLevelType
994
995     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
996     {
997         return -1;
998     }
999
1000     */
1001
1002     mid = messageid;
1003
1004     log->args_num = 0;
1005     log->log_level = loglevel;
1006     log->size = 0;
1007
1008     if (dlt_user.dlt_ll_ts==0)
1009     {
1010         return -1;
1011     }
1012
1013     DLT_SEM_LOCK();
1014
1015     if ((log->log_level<=(int)(dlt_user.dlt_ll_ts[handle->log_level_pos].log_level) ) && (log->log_level!=0))
1016     {
1017         DLT_SEM_FREE();
1018
1019         /* In non-verbose mode, insert message id */
1020         if (dlt_user.verbose_mode==0)
1021         {
1022             if ((sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1023             {
1024                 return -1;
1025             }
1026             /* Write message id */
1027             memcpy(log->buffer,&(mid),sizeof(uint32_t));
1028             log->size = sizeof(uint32_t);
1029
1030             /* as the message id is part of each message in non-verbose mode,
1031                it doesn't increment the argument counter in extended header (if used) */
1032         }
1033         return 1;
1034     }
1035     else
1036     {
1037         DLT_SEM_FREE();
1038         return 0;
1039     }
1040
1041     return -1;
1042 }
1043
1044 int dlt_user_log_write_finish(DltContextData *log)
1045 {
1046     if (log==0)
1047     {
1048         return -1;
1049     }
1050
1051     return dlt_user_log_send_log(log, DLT_TYPE_LOG);
1052 }
1053
1054 int dlt_user_log_write_raw(DltContextData *log,void *data,uint16_t length)
1055 {
1056     uint16_t arg_size;
1057     uint32_t type_info;
1058
1059     if (log==0)
1060     {
1061         return -1;
1062     }
1063
1064     if ((log->size+length+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1065     {
1066         return -1;
1067     }
1068
1069     if (dlt_user.verbose_mode)
1070     {
1071         if ((log->size+length+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1072         {
1073             return -1;
1074         }
1075
1076         /* Transmit type information */
1077         type_info = DLT_TYPE_INFO_RAWD;
1078
1079         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1080         log->size += sizeof(uint32_t);
1081
1082     }
1083
1084     /* First transmit length of raw data, then the raw data itself */
1085     arg_size = (uint16_t)length;
1086
1087     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1088     log->size += sizeof(uint16_t);
1089
1090     memcpy((log->buffer)+log->size,data,arg_size);
1091     log->size += arg_size;
1092
1093     log->args_num ++;
1094
1095     return 0;
1096 }
1097
1098 int dlt_user_log_write_float32(DltContextData *log, float32_t data)
1099 {
1100     uint32_t type_info;
1101
1102     if (log==0)
1103     {
1104         return -1;
1105     }
1106
1107     if (sizeof(float32_t)!=4)
1108     {
1109         return -1;
1110     }
1111
1112     if ((log->size+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1113     {
1114         return -1;
1115     }
1116
1117     if (dlt_user.verbose_mode)
1118     {
1119         if ((log->size+sizeof(uint32_t)+sizeof(float32_t))>DLT_USER_BUF_MAX_SIZE)
1120         {
1121             return -1;
1122         }
1123
1124         type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_32BIT;
1125
1126         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1127         log->size += sizeof(uint32_t);
1128     }
1129
1130     memcpy((log->buffer)+log->size,&data, sizeof(float32_t));
1131     log->size += sizeof(float32_t);
1132
1133     log->args_num ++;
1134
1135     return 0;
1136 }
1137
1138 int dlt_user_log_write_float64(DltContextData *log, float64_t data)
1139 {
1140     uint32_t type_info;
1141
1142     if (log==0)
1143     {
1144         return -1;
1145     }
1146
1147     if (sizeof(float64_t)!=8)
1148     {
1149         return -1;
1150     }
1151
1152     if ((log->size+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1153     {
1154         return -1;
1155     }
1156
1157     if (dlt_user.verbose_mode)
1158     {
1159         if ((log->size+sizeof(uint32_t)+sizeof(float64_t))>DLT_USER_BUF_MAX_SIZE)
1160         {
1161             return -1;
1162         }
1163
1164         type_info = DLT_TYPE_INFO_FLOA | DLT_TYLE_64BIT;
1165
1166         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1167         log->size += sizeof(uint32_t);
1168     }
1169
1170     memcpy((log->buffer)+log->size,&data, sizeof(float64_t));
1171     log->size += sizeof(float64_t);
1172
1173     log->args_num ++;
1174
1175     return 0;
1176 }
1177
1178 int dlt_user_log_write_uint( DltContextData *log, unsigned int data)
1179 {
1180     if (log==0)
1181     {
1182         return -1;
1183     }
1184
1185     switch (sizeof(unsigned int))
1186     {
1187     case 1:
1188     {
1189         return dlt_user_log_write_uint8(log, (uint8_t)data);
1190         break;
1191     }
1192     case 2:
1193     {
1194         return dlt_user_log_write_uint16(log, (uint16_t)data);
1195         break;
1196     }
1197     case 4:
1198     {
1199         return dlt_user_log_write_uint32(log, (uint32_t)data);
1200         break;
1201     }
1202     case 8:
1203     {
1204         return dlt_user_log_write_uint64(log, (uint64_t)data);
1205                 break;
1206     }
1207     default:
1208     {
1209         return -1;
1210         break;
1211     }
1212     }
1213
1214     return 0;
1215 }
1216
1217 int dlt_user_log_write_uint8(DltContextData *log, uint8_t data)
1218 {
1219     uint32_t type_info;
1220
1221     if (log==0)
1222     {
1223         return -1;
1224     }
1225
1226     if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1227     {
1228         return -1;
1229     }
1230
1231     if (dlt_user.verbose_mode)
1232     {
1233         if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1234         {
1235             return -1;
1236         }
1237
1238         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_8BIT;
1239
1240         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1241         log->size += sizeof(uint32_t);
1242     }
1243
1244     memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1245     log->size += sizeof(uint8_t);
1246
1247     log->args_num ++;
1248
1249     return 0;
1250 }
1251
1252 int dlt_user_log_write_uint16(DltContextData *log, uint16_t data)
1253 {
1254     uint32_t type_info;
1255
1256     if (log==0)
1257     {
1258         return -1;
1259     }
1260
1261     if ((log->size+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1262     {
1263         return -1;
1264     }
1265
1266     if (dlt_user.verbose_mode)
1267     {
1268         if ((log->size+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1269         {
1270             return -1;
1271         }
1272
1273         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_16BIT;
1274
1275         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1276         log->size += sizeof(uint32_t);
1277     }
1278
1279     memcpy((log->buffer)+log->size,&data,sizeof(uint16_t));
1280     log->size += sizeof(uint16_t);
1281
1282     log->args_num ++;
1283
1284     return 0;
1285 }
1286
1287 int dlt_user_log_write_uint32(DltContextData *log, uint32_t data)
1288 {
1289     uint32_t type_info;
1290
1291     if (log==0)
1292     {
1293         return -1;
1294     }
1295
1296     if ((log->size+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1297     {
1298         return -1;
1299     }
1300
1301     if (dlt_user.verbose_mode)
1302     {
1303         if ((log->size+sizeof(uint32_t)+sizeof(uint32_t))>DLT_USER_BUF_MAX_SIZE)
1304         {
1305             return -1;
1306         }
1307
1308         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_32BIT;
1309
1310         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1311         log->size += sizeof(uint32_t);
1312     }
1313
1314     memcpy((log->buffer)+log->size,&data, sizeof(uint32_t));
1315     log->size += sizeof(uint32_t);
1316
1317     log->args_num ++;
1318
1319     return 0;
1320 }
1321
1322 int dlt_user_log_write_uint64(DltContextData *log, uint64_t data)
1323 {
1324     uint32_t type_info;
1325
1326     if (log==0)
1327     {
1328         return -1;
1329     }
1330
1331     if ((log->size+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1332     {
1333         return -1;
1334     }
1335
1336     if (dlt_user.verbose_mode)
1337     {
1338         if ((log->size+sizeof(uint32_t)+sizeof(uint64_t))>DLT_USER_BUF_MAX_SIZE)
1339         {
1340             return -1;
1341         }
1342
1343         type_info = DLT_TYPE_INFO_UINT | DLT_TYLE_64BIT;
1344
1345         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1346         log->size +=sizeof(uint32_t);
1347     }
1348
1349     memcpy((log->buffer)+log->size,&data,sizeof(uint64_t));
1350     log->size += sizeof(uint64_t);
1351
1352     log->args_num ++;
1353
1354     return 0;
1355 }
1356
1357 int dlt_user_log_write_int(DltContextData *log, int data)
1358 {
1359     if (log==0)
1360     {
1361         return -1;
1362     }
1363
1364     switch (sizeof(int))
1365     {
1366     case 1:
1367     {
1368         return dlt_user_log_write_int8(log, (int8_t)data);
1369         break;
1370     }
1371     case 2:
1372     {
1373         return dlt_user_log_write_int16(log, (int16_t)data);
1374         break;
1375     }
1376     case 4:
1377     {
1378         return dlt_user_log_write_int32(log, (int32_t)data);
1379         break;
1380     }
1381     case 8:
1382     {
1383         return dlt_user_log_write_int64(log, (int64_t)data);
1384                 break;
1385     }
1386     default:
1387     {
1388         return -1;
1389         break;
1390     }
1391     }
1392
1393     return 0;
1394 }
1395
1396 int dlt_user_log_write_int8(DltContextData *log, int8_t data)
1397 {
1398     uint32_t type_info;
1399
1400     if (log==0)
1401     {
1402         return -1;
1403     }
1404
1405     if ((log->size+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1406     {
1407         return -1;
1408     }
1409
1410     if (dlt_user.verbose_mode)
1411     {
1412         if ((log->size+sizeof(uint32_t)+sizeof(int8_t))>DLT_USER_BUF_MAX_SIZE)
1413         {
1414             return -1;
1415         }
1416
1417         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_8BIT;
1418
1419         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1420         log->size += sizeof(uint32_t);
1421     }
1422
1423     memcpy((log->buffer)+log->size,&data,sizeof(int8_t));
1424     log->size += sizeof(int8_t);
1425
1426     log->args_num ++;
1427
1428     return 0;
1429 }
1430
1431 int dlt_user_log_write_int16(DltContextData *log, int16_t data)
1432 {
1433     uint32_t type_info;
1434
1435     if (log==0)
1436     {
1437         return -1;
1438     }
1439
1440     if ((log->size+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1441     {
1442         return -1;
1443     }
1444
1445     if (dlt_user.verbose_mode)
1446     {
1447         if ((log->size+sizeof(uint32_t)+sizeof(int16_t))>DLT_USER_BUF_MAX_SIZE)
1448                 {
1449             return -1;
1450                 }
1451
1452         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_16BIT;
1453
1454         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1455         log->size += sizeof(uint32_t);
1456     }
1457
1458     memcpy((log->buffer)+log->size,&data,sizeof(int16_t));
1459     log->size += sizeof(int16_t);
1460
1461     log->args_num ++;
1462
1463     return 0;
1464 }
1465
1466 int dlt_user_log_write_int32(DltContextData *log, int32_t data)
1467 {
1468     uint32_t type_info;
1469
1470     if (log==0)
1471     {
1472         return -1;
1473     }
1474
1475     if ((log->size+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1476     {
1477         return -1;
1478     }
1479
1480     if (dlt_user.verbose_mode)
1481     {
1482         if ((log->size+sizeof(uint32_t)+sizeof(int32_t))>DLT_USER_BUF_MAX_SIZE)
1483         {
1484             return -1;
1485         }
1486
1487         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_32BIT;
1488
1489         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1490         log->size += sizeof(uint32_t);
1491     }
1492
1493     memcpy((log->buffer)+log->size,&data, sizeof(int32_t));
1494     log->size += sizeof(int32_t);
1495
1496     log->args_num ++;
1497
1498     return 0;
1499 }
1500
1501 int dlt_user_log_write_int64(DltContextData *log, int64_t data)
1502 {
1503     uint32_t type_info;
1504
1505     if (log==0)
1506     {
1507         return -1;
1508     }
1509
1510     if ((log->size+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1511     {
1512         return -1;
1513     }
1514
1515     if (dlt_user.verbose_mode)
1516     {
1517         if ((log->size+sizeof(uint32_t)+sizeof(int64_t))>DLT_USER_BUF_MAX_SIZE)
1518         {
1519             return -1;
1520         }
1521
1522         type_info = DLT_TYPE_INFO_SINT | DLT_TYLE_64BIT;
1523
1524         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1525         log->size += sizeof(uint32_t);
1526     }
1527
1528     memcpy((log->buffer)+log->size,&data,sizeof(int64_t));
1529     log->size += sizeof(int64_t);
1530
1531     log->args_num ++;
1532
1533     return 0;
1534 }
1535
1536 int dlt_user_log_write_bool(DltContextData *log, uint8_t data)
1537 {
1538     uint32_t type_info;
1539
1540     if (log==0)
1541     {
1542         return -1;
1543     }
1544
1545     if ((log->size+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1546     {
1547         return -1;
1548     }
1549
1550     if (dlt_user.verbose_mode)
1551     {
1552         if ((log->size+sizeof(uint32_t)+sizeof(uint8_t))>DLT_USER_BUF_MAX_SIZE)
1553         {
1554             return -1;
1555         }
1556
1557         type_info = DLT_TYPE_INFO_BOOL;
1558
1559         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1560         log->size += sizeof(uint32_t);
1561     }
1562
1563     memcpy((log->buffer)+log->size,&data,sizeof(uint8_t));
1564     log->size += sizeof(uint8_t);
1565
1566     log->args_num ++;
1567
1568     return 0;
1569 }
1570
1571 int dlt_user_log_write_string(DltContextData *log, const char *text)
1572 {
1573     uint16_t arg_size;
1574     uint32_t type_info;
1575
1576     if ((log==0) || (text==0))
1577     {
1578         return -1;
1579     }
1580
1581     if ((log->size+(strlen(text)+1)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1582     {
1583         return -1;
1584     }
1585
1586     if (dlt_user.verbose_mode)
1587     {
1588         if ((log->size+(strlen(text)+1)+sizeof(uint32_t)+sizeof(uint16_t))>DLT_USER_BUF_MAX_SIZE)
1589         {
1590             return -1;
1591         }
1592
1593         type_info = DLT_TYPE_INFO_STRG;
1594
1595         memcpy((log->buffer)+log->size,&(type_info),sizeof(uint32_t));
1596         log->size += sizeof(uint32_t);
1597     }
1598
1599     arg_size = strlen(text) + 1;
1600
1601     memcpy((log->buffer)+log->size,&(arg_size),sizeof(uint16_t));
1602     log->size += sizeof(uint16_t);
1603
1604     memcpy((log->buffer)+log->size,text,arg_size);
1605     log->size += arg_size;
1606
1607     log->args_num ++;
1608
1609     return 0;
1610 }
1611
1612 int dlt_register_injection_callback(DltContext *handle, uint32_t service_id,
1613                                     int (*dlt_injection_callback)(uint32_t service_id, void *data, uint32_t length))
1614 {
1615     DltContextData log;
1616     uint32_t i,j,k;
1617     int found = 0;
1618
1619         DltUserInjectionCallback *old;
1620
1621     if (handle==0)
1622     {
1623         return -1;
1624     }
1625
1626     if (dlt_user_log_init(handle, &log)==-1)
1627     {
1628                 return -1;
1629     }
1630
1631     if (service_id<DLT_USER_INJECTION_MIN)
1632     {
1633         return -1;
1634     }
1635     /* This function doesn't make sense storing to local file is choosen;
1636        so terminate this function */
1637     if (dlt_user.dlt_is_file)
1638     {
1639         return 0;
1640     }
1641
1642     DLT_SEM_LOCK();
1643
1644     if (dlt_user.dlt_ll_ts==0)
1645     {
1646         DLT_SEM_FREE();
1647         return 0;
1648     }
1649
1650     /* Insert callback in corresponding table */
1651     i=handle->log_level_pos;
1652
1653     /* Insert each service_id only once */
1654     for (k=0;k<dlt_user.dlt_ll_ts[i].nrcallbacks;k++)
1655     {
1656         if ((dlt_user.dlt_ll_ts[i].injection_table) &&
1657                 (dlt_user.dlt_ll_ts[i].injection_table[k].service_id == service_id))
1658         {
1659             found = 1;
1660             break;
1661         }
1662     }
1663
1664     if (found)
1665     {
1666         j = k;
1667     }
1668     else
1669     {
1670         j=dlt_user.dlt_ll_ts[i].nrcallbacks;
1671
1672         /* Allocate or expand injection table */
1673         if (dlt_user.dlt_ll_ts[i].injection_table == 0)
1674         {
1675             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback));
1676         }
1677         else
1678         {
1679             old = dlt_user.dlt_ll_ts[i].injection_table;
1680             dlt_user.dlt_ll_ts[i].injection_table = (DltUserInjectionCallback*) malloc(sizeof(DltUserInjectionCallback)*(j+1));
1681             memcpy(dlt_user.dlt_ll_ts[i].injection_table,old,sizeof(DltUserInjectionCallback)*j);
1682             free(old);
1683         }
1684
1685         dlt_user.dlt_ll_ts[i].nrcallbacks++;
1686     }
1687
1688     /* Store service_id and corresponding function pointer for callback function */
1689     dlt_user.dlt_ll_ts[i].injection_table[j].service_id = service_id;
1690     dlt_user.dlt_ll_ts[i].injection_table[j].injection_callback = dlt_injection_callback;
1691
1692     DLT_SEM_FREE();
1693     return 0;
1694 }
1695
1696 int dlt_user_trace_network(DltContext *handle, DltNetworkTraceType nw_trace_type, uint16_t header_len, void *header, uint16_t payload_len, void *payload)
1697 {
1698     DltContextData log;
1699
1700     if (dlt_user_initialised==0)
1701     {
1702         if (dlt_init()<0)
1703         {
1704             return -1;
1705         }
1706     }
1707
1708     if (dlt_user_log_init(handle, &log)==-1)
1709     {
1710                 return -1;
1711     }
1712
1713     if (handle==0)
1714     {
1715         return -1;
1716     }
1717
1718     /* Commented out because of DltNetworkTraceType:
1719
1720     if ((nw_trace_type<=0) || (nw_trace_type>0x15))
1721     {
1722         return -1;
1723     }
1724
1725     */
1726
1727     DLT_SEM_LOCK();
1728
1729     if (dlt_user.dlt_ll_ts==0)
1730     {
1731         DLT_SEM_FREE();
1732         return -1;
1733     }
1734
1735     if (dlt_user.dlt_ll_ts[handle->log_level_pos].trace_status==DLT_TRACE_STATUS_ON)
1736     {
1737         DLT_SEM_FREE();
1738
1739         log.args_num = 0;
1740         log.trace_status = nw_trace_type;
1741         log.size = 0;
1742
1743         if (header==0)
1744         {
1745             header_len=0;
1746         }
1747
1748         /* Write header and its length */
1749         if (dlt_user_log_write_raw(&log, header, header_len)==-1)
1750         {
1751                 return -1;
1752         }
1753
1754         if (payload==0)
1755         {
1756             payload_len=0;
1757         }
1758
1759         /* Write payload and its length */
1760         if (dlt_user_log_write_raw(&log, payload, payload_len)==-1)
1761         {
1762                         return -1;
1763         }
1764
1765         /* Send log */
1766         return dlt_user_log_send_log(&log, DLT_TYPE_NW_TRACE);
1767     }
1768     else
1769     {
1770         DLT_SEM_FREE();
1771     }
1772
1773     return 0;
1774 }
1775
1776 int dlt_log_string(DltContext *handle,DltLogLevelType loglevel, const char *text)
1777 {
1778     DltContextData log;
1779
1780     if (dlt_user.verbose_mode==0)
1781     {
1782         return -1;
1783     }
1784
1785     if ((handle==0) || (text==0))
1786     {
1787         return -1;
1788     }
1789
1790     if (dlt_user_log_write_start(handle,&log,loglevel))
1791     {
1792         if (dlt_user_log_write_string(&log,text)==-1)
1793         {
1794                         return -1;
1795         }
1796         if (dlt_user_log_write_finish(&log)==-1)
1797         {
1798                 return -1;
1799         }
1800     }
1801
1802     return 0;
1803 }
1804
1805 int dlt_log_string_int(DltContext *handle,DltLogLevelType loglevel, const char *text, int data)
1806 {
1807     DltContextData log;
1808
1809     if (dlt_user.verbose_mode==0)
1810     {
1811         return -1;
1812     }
1813
1814     if ((handle==0) || (text==0))
1815     {
1816         return -1;
1817     }
1818
1819     if (dlt_user_log_write_start(handle,&log,loglevel))
1820     {
1821         if (dlt_user_log_write_string(&log,text)==-1)
1822         {
1823                         return -1;
1824         }
1825         if (dlt_user_log_write_int(&log,data)==-1)
1826         {
1827                         return -1;
1828         }
1829         if (dlt_user_log_write_finish(&log)==-1)
1830         {
1831                         return -1;
1832         }
1833     }
1834
1835     return 0;
1836 }
1837
1838 int dlt_log_string_uint(DltContext *handle,DltLogLevelType loglevel, const char *text, unsigned int data)
1839 {
1840     DltContextData log;
1841
1842     if (dlt_user.verbose_mode==0)
1843     {
1844         return -1;
1845     }
1846
1847     if ((handle==0) || (text==0))
1848     {
1849         return -1;
1850     }
1851
1852     if (dlt_user_log_write_start(handle,&log,loglevel))
1853     {
1854         if (dlt_user_log_write_string(&log,text)==-1)
1855         {
1856                         return -1;
1857         }
1858         if (dlt_user_log_write_uint(&log,data)==-1)
1859         {
1860                         return -1;
1861         }
1862         if (dlt_user_log_write_finish(&log)==-1)
1863         {
1864                         return -1;
1865         }
1866     }
1867
1868     return 0;
1869 }
1870
1871 int dlt_log_int(DltContext *handle,DltLogLevelType loglevel, int data)
1872 {
1873     DltContextData log;
1874
1875     if (dlt_user.verbose_mode==0)
1876     {
1877         return -1;
1878     }
1879
1880     if (handle==0)
1881     {
1882         return -1;
1883     }
1884
1885     if (dlt_user_log_write_start(handle,&log,loglevel))
1886     {
1887         if (dlt_user_log_write_int(&log,data)==-1)
1888         {
1889                         return -1;
1890         }
1891         if (dlt_user_log_write_finish(&log)==-1)
1892         {
1893                         return -1;
1894         }
1895     }
1896
1897     return 0;
1898 }
1899
1900 int dlt_log_uint(DltContext *handle,DltLogLevelType loglevel, unsigned int data)
1901 {
1902     DltContextData log;
1903
1904     if (dlt_user.verbose_mode==0)
1905     {
1906         return -1;
1907     }
1908
1909     if (handle==0)
1910     {
1911         return -1;
1912     }
1913
1914     if (dlt_user_log_write_start(handle,&log,loglevel))
1915     {
1916         if (dlt_user_log_write_uint(&log,data)==-1)
1917         {
1918                         return -1;
1919         }
1920         if (dlt_user_log_write_finish(&log)==-1)
1921         {
1922                         return -1;
1923         }
1924     }
1925
1926     return 0;
1927 }
1928
1929 int dlt_log_raw(DltContext *handle,DltLogLevelType loglevel, void *data,uint16_t length)
1930 {
1931     DltContextData log;
1932
1933     if (dlt_user.verbose_mode==0)
1934     {
1935         return -1;
1936     }
1937
1938     if (handle==0)
1939     {
1940         return -1;
1941     }
1942
1943     if (dlt_user_log_write_start(handle,&log,loglevel))
1944     {
1945         if (dlt_user_log_write_raw(&log,data,length)==-1)
1946         {
1947                         return -1;
1948         }
1949         if (dlt_user_log_write_finish(&log)==-1)
1950         {
1951                         return -1;
1952         }
1953     }
1954
1955     return 0;
1956 }
1957
1958 int dlt_verbose_mode(void)
1959 {
1960     if (dlt_user_initialised==0)
1961     {
1962         if (dlt_init()<0)
1963         {
1964             return -1;
1965         }
1966     }
1967
1968     /* Switch to verbose mode */
1969     dlt_user.verbose_mode = 1;
1970
1971     return 0;
1972 }
1973
1974 int dlt_nonverbose_mode(void)
1975 {
1976     if (dlt_user_initialised==0)
1977     {
1978         if (dlt_init()<0)
1979         {
1980             return -1;
1981         }
1982     }
1983
1984     /* Switch to non-verbose mode */
1985     dlt_user.verbose_mode = 0;
1986
1987     return 0;
1988 }
1989
1990 int dlt_enable_local_print(void)
1991 {
1992     if (dlt_user_initialised==0)
1993     {
1994         if (dlt_init()<0)
1995         {
1996             return -1;
1997         }
1998     }
1999
2000     dlt_user.enable_local_print = 1;
2001
2002     return 0;
2003 }
2004
2005 int dlt_disable_local_print(void)
2006 {
2007     if (dlt_user_initialised==0)
2008     {
2009         if (dlt_init()<0)
2010         {
2011             return -1;
2012         }
2013     }
2014
2015     dlt_user.enable_local_print = 0;
2016
2017     return 0;
2018 }
2019
2020 void dlt_user_receiverthread_function(void *ptr)
2021 {
2022     while (1)
2023     {
2024         /* Check for new messages from DLT daemon */
2025         if (dlt_user_log_check_user_message()==-1)
2026         {
2027                         /* Critical error */
2028                         dlt_log(LOG_CRIT,"Receiver thread encountered error condition\n");
2029         }
2030
2031         usleep(DLT_USER_RECEIVE_DELAY); /* delay */
2032     }
2033 }
2034
2035 /* Private functions of user library */
2036
2037 int dlt_user_log_init(DltContext *handle, DltContextData *log)
2038 {
2039     if (dlt_user_initialised==0)
2040     {
2041         if (dlt_init()<0)
2042         {
2043             return -1;
2044         }
2045     }
2046
2047     log->handle = handle;
2048
2049     return 0;
2050 }
2051
2052 int dlt_user_log_send_log(DltContextData *log, int mtype)
2053 {
2054     DltMessage msg;
2055     DltUserHeader userheader;
2056     int32_t len;
2057
2058     DltReturnValue ret = 0;
2059
2060     if (log==0)
2061     {
2062         return -1;
2063     }
2064
2065     if (log->handle==0)
2066     {
2067         return -1;
2068     }
2069
2070     if (dlt_user.appID[0]=='\0')
2071     {
2072         return -1;
2073     }
2074
2075     if (log->handle->contextID[0]=='\0')
2076     {
2077         return -1;
2078     }
2079
2080     if ((mtype<DLT_TYPE_LOG) || (mtype>DLT_TYPE_CONTROL))
2081     {
2082         return -1;
2083     }
2084
2085     /* also for Trace messages */
2086 #ifdef DLT_SHM_ENABLE
2087     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_SHM)==-1)
2088 #else
2089     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG)==-1)
2090 #endif
2091     {
2092                 return -1;
2093     }
2094
2095     if (dlt_message_init(&msg,0)==-1)
2096     {
2097         return -1;
2098     }
2099
2100     msg.storageheader = (DltStorageHeader*)msg.headerbuffer;
2101
2102     if (dlt_set_storageheader(msg.storageheader,dlt_user.ecuID)==-1)
2103     {
2104                 return -1;
2105     }
2106
2107     msg.standardheader = (DltStandardHeader*)(msg.headerbuffer + sizeof(DltStorageHeader));
2108     msg.standardheader->htyp = DLT_HTYP_WEID | DLT_HTYP_WTMS | DLT_HTYP_PROTOCOL_VERSION1 ;
2109
2110     if (dlt_user.verbose_mode)
2111     {
2112         /* In verbose mode, send extended header */
2113         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2114     }
2115     else
2116     {
2117         /* In non-verbose, send extended header if desired */
2118 #if (DLT_USER_USE_EXTENDED_HEADER_FOR_NONVERBOSE==1)
2119         msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_UEH );
2120 #endif
2121     }
2122
2123 #if (BYTE_ORDER==BIG_ENDIAN)
2124     msg.standardheader->htyp = (msg.standardheader->htyp | DLT_HTYP_MSBF);
2125 #endif
2126
2127     msg.standardheader->mcnt = log->handle->mcnt++;
2128
2129     /* Set header extra parameters */
2130     dlt_set_id(msg.headerextra.ecu,dlt_user.ecuID);
2131     //msg.headerextra.seid = 0;
2132     msg.headerextra.tmsp = dlt_uptime();
2133
2134     if (dlt_message_set_extraparameters(&msg,0)==-1)
2135     {
2136         return -1;
2137     }
2138
2139     /* Fill out extended header, if extended header should be provided */
2140     if (DLT_IS_HTYP_UEH(msg.standardheader->htyp))
2141     {
2142         /* with extended header */
2143         msg.extendedheader = (DltExtendedHeader*)(msg.headerbuffer + sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp)  );
2144
2145         switch (mtype)
2146         {
2147         case DLT_TYPE_LOG:
2148         {
2149             msg.extendedheader->msin = (DLT_TYPE_LOG << DLT_MSIN_MSTP_SHIFT) | ((log->log_level << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2150             break;
2151         }
2152         case DLT_TYPE_NW_TRACE:
2153         {
2154             msg.extendedheader->msin = (DLT_TYPE_NW_TRACE << DLT_MSIN_MSTP_SHIFT) | ((log->trace_status << DLT_MSIN_MTIN_SHIFT) & DLT_MSIN_MTIN) ; /* messsage info */
2155             break;
2156         }
2157         default:
2158         {
2159                     /* This case should not occur */
2160             return -1;
2161             break;
2162         }
2163         }
2164
2165         /* If in verbose mode, set flag in header for verbose mode */
2166         if (dlt_user.verbose_mode)
2167         {
2168             msg.extendedheader->msin |= DLT_MSIN_VERB;
2169         }
2170
2171         msg.extendedheader->noar = log->args_num;              /* number of arguments */
2172         dlt_set_id(msg.extendedheader->apid,dlt_user.appID);       /* application id */
2173         dlt_set_id(msg.extendedheader->ctid,log->handle->contextID);   /* context id */
2174
2175         msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + sizeof(DltExtendedHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2176     }
2177     else
2178     {
2179         /* without extended header */
2180         msg.headersize = sizeof(DltStorageHeader) + sizeof(DltStandardHeader) + DLT_STANDARD_HEADER_EXTRA_SIZE(msg.standardheader->htyp);
2181     }
2182
2183     len=msg.headersize - sizeof(DltStorageHeader) +log->size;
2184     if (len>UINT16_MAX)
2185     {
2186         dlt_log(LOG_CRIT,"Huge message discarded!\n");
2187         return -1;
2188     }
2189
2190     msg.standardheader->len = DLT_HTOBE_16(len);
2191
2192     /* print to std out, if enabled */
2193     if ((dlt_user.local_print_mode != DLT_PM_FORCE_OFF) &&
2194             (dlt_user.local_print_mode != DLT_PM_AUTOMATIC))
2195     {
2196         if ((dlt_user.enable_local_print) || (dlt_user.local_print_mode == DLT_PM_FORCE_ON))
2197         {
2198             if (dlt_user_print_msg(&msg, log)==-1)
2199             {
2200                                 return -1;
2201             }
2202         }
2203     }
2204
2205     if (dlt_user.dlt_is_file)
2206     {
2207         /* log to file */
2208         ret=dlt_user_log_out2(dlt_user.dlt_log_handle, msg.headerbuffer, msg.headersize, log->buffer, log->size);
2209         return ((ret==DLT_RETURN_OK)?0:-1);
2210     }
2211     else
2212     {
2213         /* Reattach to daemon if neccesary */
2214         dlt_user_log_reattach_to_daemon();
2215
2216         if (dlt_user.overflow)
2217         {
2218             if (dlt_user_log_send_overflow()==0)
2219             {
2220                 dlt_user.overflow=0;
2221             }
2222         }
2223
2224                 /* try to resent old data first */
2225                 ret = 0;
2226                 if(dlt_user.dlt_log_handle!=-1)
2227                         ret = dlt_user_log_resend_buffer();
2228                 if(ret==0) 
2229                 {
2230                         /* resend ok or nothing to resent */
2231 #ifdef DLT_SHM_ENABLE
2232                         if(dlt_user.dlt_log_handle!=-1)
2233                                 dlt_shm_push(&dlt_user.dlt_shm,msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
2234                                                                                         log->buffer, log->size,0,0);                   
2235
2236                         /* log to FIFO */
2237                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
2238                                                                         &(userheader), sizeof(DltUserHeader),
2239                                                                         0, 0,
2240                                                                         0, 0);
2241 #else
2242                         /* log to FIFO */
2243 #ifdef DLT_TEST_ENABLE
2244                         if(dlt_user.corrupt_user_header) {
2245                                 userheader.pattern[0]=0xff;
2246                                 userheader.pattern[1]=0xff;
2247                                 userheader.pattern[2]=0xff;
2248                                 userheader.pattern[3]=0xff;
2249                         }
2250                         if(dlt_user.corrupt_message_size) {
2251                                 msg.standardheader->len = DLT_HTOBE_16(dlt_user.corrupt_message_size_size);
2252                         }
2253 #endif
2254                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle,
2255                                                                         &(userheader), sizeof(DltUserHeader),
2256                                                                         msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
2257                                                                         log->buffer, log->size);                
2258 #endif                  
2259                 }
2260                 
2261         /* store message in ringbuffer, if an error has occured */
2262         if (ret!=DLT_RETURN_OK)
2263         {
2264             DLT_SEM_LOCK();
2265
2266             if (dlt_buffer_push3(&(dlt_user.startup_buffer),
2267                                 (unsigned char *)&(userheader), sizeof(DltUserHeader),
2268                                 msg.headerbuffer+sizeof(DltStorageHeader), msg.headersize-sizeof(DltStorageHeader),
2269                                 log->buffer, log->size)==-1)
2270                         {
2271                                 dlt_log(LOG_ERR,"Storing message to history buffer failed! Message discarded.\n");
2272                         }
2273
2274             DLT_SEM_FREE();
2275         }
2276
2277         switch (ret)
2278         {
2279         case DLT_RETURN_PIPE_FULL:
2280         {
2281             /* data could not be written */
2282             dlt_user.overflow = 1;
2283             return -1;
2284         }
2285         case DLT_RETURN_PIPE_ERROR:
2286         {
2287             /* handle not open or pipe error */
2288             close(dlt_user.dlt_log_handle);
2289             dlt_user.dlt_log_handle = -1;
2290
2291 #ifdef DLT_SHM_ENABLE
2292                         /* free shared memory */
2293                         dlt_shm_free_client(&dlt_user.dlt_shm);
2294 #endif
2295
2296             if (dlt_user.local_print_mode == DLT_PM_AUTOMATIC)
2297             {
2298                 dlt_user_print_msg(&msg, log);
2299             }
2300
2301             return -1;
2302         }
2303         case DLT_RETURN_ERROR:
2304         {
2305             /* other error condition */
2306             return -1;
2307         }
2308                 case DLT_RETURN_OK:
2309         {
2310                 return 0;
2311         }
2312                 default:
2313                 {
2314                         /* This case should never occur. */
2315                         return -1;
2316                 }
2317         }
2318     }
2319
2320     return 0;
2321 }
2322
2323 int dlt_user_log_send_register_application(void)
2324 {
2325     DltUserHeader userheader;
2326     DltUserControlMsgRegisterApplication usercontext;
2327
2328     DltReturnValue ret;
2329
2330     if (dlt_user.appID[0]=='\0')
2331     {
2332         return -1;
2333     }
2334
2335     /* set userheader */
2336     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_APPLICATION)==-1)
2337     {
2338                 return -1;
2339     }
2340
2341     /* set usercontext */
2342     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
2343     usercontext.pid = getpid();
2344
2345     if (dlt_user.application_description!=0)
2346     {
2347         usercontext.description_length = strlen(dlt_user.application_description);
2348     }
2349     else
2350     {
2351         usercontext.description_length = 0;
2352     }
2353
2354     if (dlt_user.dlt_is_file)
2355     {
2356         return 0;
2357     }
2358
2359     /* log to FIFO */
2360     ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterApplication),dlt_user.application_description,usercontext.description_length);
2361         return ((ret==DLT_RETURN_OK)?0:-1);
2362 }
2363
2364 int dlt_user_log_send_unregister_application(void)
2365 {
2366     DltUserHeader userheader;
2367     DltUserControlMsgUnregisterApplication usercontext;
2368
2369     DltReturnValue ret;
2370
2371     if (dlt_user.appID[0]=='\0')
2372     {
2373         return -1;
2374     }
2375
2376     /* set userheader */
2377     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_APPLICATION)==-1)
2378     {
2379         return -1;
2380     }
2381
2382     /* set usercontext */
2383     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
2384     usercontext.pid = getpid();
2385
2386     if (dlt_user.dlt_is_file)
2387     {
2388         return 0;
2389     }
2390
2391     /* log to FIFO */
2392     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterApplication));
2393     return ((ret==DLT_RETURN_OK)?0:-1);
2394 }
2395
2396 int dlt_user_log_send_register_context(DltContextData *log)
2397 {
2398     DltUserHeader userheader;
2399     DltUserControlMsgRegisterContext usercontext;
2400     DltReturnValue ret;
2401
2402     if (log==0)
2403     {
2404                 return -1;
2405     }
2406
2407     if (log->handle==0)
2408     {
2409         return -1;
2410     }
2411
2412     if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
2413     {
2414         return -1;
2415     }
2416
2417     /* set userheader */
2418     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_REGISTER_CONTEXT)==-1)
2419     {
2420                 return -1;
2421     }
2422
2423     /* set usercontext */
2424     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
2425     dlt_set_id(usercontext.ctid,log->handle->contextID);       /* context id */
2426     usercontext.log_level_pos = log->handle->log_level_pos;
2427     usercontext.pid = getpid();
2428
2429     usercontext.log_level = (int8_t)log->log_level;
2430     usercontext.trace_status = (int8_t)log->trace_status;
2431
2432     if (log->context_description!=0)
2433     {
2434         usercontext.description_length = strlen(log->context_description);
2435     }
2436     else
2437     {
2438                 usercontext.description_length = 0;
2439     }
2440
2441     if (dlt_user.dlt_is_file)
2442     {
2443         return 0;
2444     }
2445
2446     /* log to FIFO */
2447     ret=dlt_user_log_out3(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgRegisterContext),log->context_description,usercontext.description_length);
2448     return ((ret==DLT_RETURN_OK)?0:-1);
2449 }
2450
2451 int dlt_user_log_send_unregister_context(DltContextData *log)
2452 {
2453     DltUserHeader userheader;
2454     DltUserControlMsgUnregisterContext usercontext;
2455     DltReturnValue ret;
2456
2457     if (log==0)
2458     {
2459         return -1;
2460     }
2461
2462     if (log->handle==0)
2463     {
2464         return -1;
2465     }
2466
2467     if ((dlt_user.appID[0]=='\0') || (log->handle->contextID=='\0'))
2468     {
2469         return -1;
2470     }
2471
2472     /* set userheader */
2473     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_UNREGISTER_CONTEXT)==-1)
2474     {
2475                 return -1;
2476     }
2477
2478     /* set usercontext */
2479     dlt_set_id(usercontext.apid,dlt_user.appID);       /* application id */
2480     dlt_set_id(usercontext.ctid,log->handle->contextID);       /* context id */
2481     usercontext.pid = getpid();
2482
2483     if (dlt_user.dlt_is_file)
2484     {
2485         return 0;
2486     }
2487
2488     /* log to FIFO */
2489     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgUnregisterContext));
2490         return ((ret==DLT_RETURN_OK)?0:-1);
2491 }
2492
2493 int dlt_send_app_ll_ts_limit(const char *appid, DltLogLevelType loglevel, DltTraceStatusType tracestatus)
2494 {
2495     DltUserHeader userheader;
2496     DltUserControlMsgAppLogLevelTraceStatus usercontext;
2497         DltReturnValue ret;
2498
2499     if ((appid==0) || (appid[0]=='\0'))
2500     {
2501         return -1;
2502     }
2503
2504     /* Removed because of DltLogLevelType and DltTraceStatusType
2505
2506     if ((loglevel<DLT_LOG_DEFAULT) || (loglevel>DLT_LOG_VERBOSE))
2507     {
2508         return -1;
2509     }
2510
2511     if ((tracestatus<DLT_TRACE_STATUS_DEFAULT) || (tracestatus>DLT_TRACE_STATUS_ON))
2512     {
2513         return -1;
2514     }
2515
2516     */
2517
2518     /* set userheader */
2519     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_APP_LL_TS)==-1)
2520     {
2521                 return -1;
2522     }
2523
2524     /* set usercontext */
2525     dlt_set_id(usercontext.apid,appid);       /* application id */
2526     usercontext.log_level = loglevel;
2527     usercontext.trace_status = tracestatus;
2528
2529     if (dlt_user.dlt_is_file)
2530     {
2531         return 0;
2532     }
2533
2534     /* log to FIFO */
2535     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(usercontext), sizeof(DltUserControlMsgAppLogLevelTraceStatus));
2536     return ((ret==DLT_RETURN_OK)?0:-1);
2537 }
2538
2539 int dlt_user_log_send_log_mode(DltUserLogMode mode)
2540 {
2541     DltUserHeader userheader;
2542     DltUserControlMsgLogMode logmode;
2543
2544     DltReturnValue ret;
2545
2546     /* set userheader */
2547     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_MODE)==-1)
2548     {
2549         return -1;
2550     }
2551
2552     /* set data */
2553     logmode.log_mode = (unsigned char) mode;
2554
2555     if (dlt_user.dlt_is_file)
2556     {
2557         return 0;
2558     }
2559
2560     /* log to FIFO */
2561     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), &(logmode), sizeof(DltUserControlMsgLogMode));
2562     return ((ret==DLT_RETURN_OK)?0:-1);
2563 }
2564
2565 int dlt_user_print_msg(DltMessage *msg, DltContextData *log)
2566 {
2567     uint8_t *databuffer_tmp;
2568     int32_t datasize_tmp;
2569     static char text[DLT_USER_TEXT_LENGTH];
2570
2571     if ((msg==0) || (log==0))
2572     {
2573         return -1;
2574     }
2575
2576     /* Save variables before print */
2577     databuffer_tmp = msg->databuffer;
2578     datasize_tmp = msg->datasize;
2579
2580     /* Act like a receiver, convert header back to host format */
2581     msg->standardheader->len = DLT_BETOH_16(msg->standardheader->len);
2582     dlt_message_get_extraparameters(msg,0);
2583
2584     msg->databuffer = log->buffer;
2585     msg->datasize = log->size;
2586
2587     /* Print message as ASCII */
2588     if (dlt_message_print_ascii(msg,text,DLT_USER_TEXT_LENGTH,0)==-1)
2589     {
2590                 return -1;
2591     }
2592
2593     /* Restore variables and set len to BE*/
2594     msg->databuffer = databuffer_tmp;
2595     msg->datasize =  datasize_tmp;
2596
2597     msg->standardheader->len = DLT_HTOBE_16(msg->standardheader->len);
2598
2599     return 0;
2600 }
2601
2602 int dlt_user_log_check_user_message(void)
2603 {
2604     int offset=0;
2605     int leave_while=0;
2606
2607     uint32_t i;
2608
2609     DltUserHeader *userheader;
2610     DltReceiver *receiver = &(dlt_user.receiver);
2611
2612     DltUserControlMsgLogLevel *usercontextll;
2613     DltUserControlMsgInjection *usercontextinj;
2614     DltUserControlMsgLogState *userlogstate;
2615     unsigned char *userbuffer;
2616     unsigned char *inject_buffer;
2617
2618     if (dlt_user.dlt_user_handle!=-1)
2619     {
2620         while (1)
2621         {
2622             if (dlt_receiver_receive_fd(receiver)<=0)
2623             {
2624                 /* No new message available */
2625                 return 0;
2626             }
2627
2628             /* look through buffer as long as data is in there */
2629             while (1)
2630             {
2631                 if (receiver->bytesRcvd < (int32_t)sizeof(DltUserHeader))
2632                 {
2633                     break;
2634                 }
2635
2636                 /* resync if necessary */
2637                 offset=0;
2638                 do
2639                 {
2640                     userheader = (DltUserHeader*) (receiver->buf+offset);
2641
2642                     /* Check for user header pattern */
2643                     if (dlt_user_check_userheader(userheader))
2644                     {
2645                         break;
2646                     }
2647                     offset++;
2648
2649                 }
2650                 while ((int32_t)(sizeof(DltUserHeader)+offset)<=receiver->bytesRcvd);
2651
2652                 /* Check for user header pattern */
2653                 if (dlt_user_check_userheader(userheader)==0)
2654                 {
2655                     break;
2656                 }
2657
2658                 /* Set new start offset */
2659                 if (offset>0)
2660                 {
2661                     receiver->buf+=offset;
2662                     receiver->bytesRcvd-=offset;
2663                 }
2664
2665                 switch (userheader->message)
2666                 {
2667                 case DLT_USER_MESSAGE_LOG_LEVEL:
2668                 {
2669                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel)))
2670                     {
2671                         leave_while=1;
2672                         break;
2673                     }
2674
2675                     usercontextll = (DltUserControlMsgLogLevel*) (receiver->buf+sizeof(DltUserHeader));
2676
2677                     /* Update log level and trace status */
2678                     if (usercontextll!=0)
2679                     {
2680                         DLT_SEM_LOCK();
2681
2682                         if ((usercontextll->log_level_pos >= 0) && (usercontextll->log_level_pos < (int32_t)dlt_user.dlt_ll_ts_num_entries))
2683                         {
2684                             // printf("Store ll, ts\n");
2685                             if (dlt_user.dlt_ll_ts)
2686                             {
2687                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].log_level = usercontextll->log_level;
2688                                 dlt_user.dlt_ll_ts[usercontextll->log_level_pos].trace_status = usercontextll->trace_status;
2689                             }
2690                         }
2691
2692                         DLT_SEM_FREE();
2693                     }
2694
2695                     /* keep not read data in buffer */
2696                     if (dlt_receiver_remove(receiver,sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogLevel))==-1)
2697                     {
2698                         return -1;
2699                     }
2700                 }
2701                 break;
2702                 case DLT_USER_MESSAGE_INJECTION:
2703                 {
2704                     /* At least, user header, user context, and service id and data_length of injected message is available */
2705                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)))
2706                     {
2707                         leave_while = 1;
2708                         break;
2709                     }
2710
2711                     usercontextinj = (DltUserControlMsgInjection*) (receiver->buf+sizeof(DltUserHeader));
2712                     userbuffer = (unsigned char*) (receiver->buf+sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection));
2713                     inject_buffer = 0;
2714
2715                     if (userbuffer!=0)
2716                     {
2717
2718                         if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))
2719                         {
2720                             leave_while = 1;
2721                             break;
2722                         }
2723
2724                         DLT_SEM_LOCK();
2725
2726                         if ((usercontextinj->data_length_inject>0) && (dlt_user.dlt_ll_ts))
2727                         {
2728                             /* Check if injection callback is registered for this context */
2729                             for (i=0; i<dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].nrcallbacks;i++)
2730                             {
2731                                 if ((dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table) &&
2732                                         (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].service_id == usercontextinj->service_id))
2733                                 {
2734                                     /* callback available, so prepare data, then call it */
2735                                     inject_buffer = malloc(usercontextinj->data_length_inject);
2736                                     if (inject_buffer!=0)
2737                                     {
2738                                         /* copy from receiver to inject_buffer */
2739                                         memcpy(inject_buffer, userbuffer, usercontextinj->data_length_inject);
2740
2741                                         /* call callback */
2742                                         if (dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback!=0)
2743                                         {
2744                                             // printf("Got injection(%d), length=%d, '%s' \n", usercontext->service_id, usercontext->data_length_inject, inject_buffer);
2745                                             dlt_user.dlt_ll_ts[usercontextinj->log_level_pos].injection_table[i].injection_callback(
2746                                                 usercontextinj->service_id, inject_buffer, usercontextinj->data_length_inject);
2747                                         }
2748
2749                                         if (inject_buffer!=0)
2750                                         {
2751                                             free(inject_buffer);
2752                                             inject_buffer = 0;
2753                                         }
2754                                     }
2755
2756                                     break;
2757                                 }
2758                             }
2759                         }
2760
2761                         DLT_SEM_FREE();
2762
2763                         /* keep not read data in buffer */
2764                         if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgInjection)+usercontextinj->data_length_inject))==-1)
2765                                                 {
2766                                                         return -1;
2767                                                 }
2768                     }
2769                 }
2770                 break;
2771                 case DLT_USER_MESSAGE_LOG_STATE:
2772                 {
2773                     /* At least, user header, user context, and service id and data_length of injected message is available */
2774                     if (receiver->bytesRcvd < (int32_t)(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))
2775                     {
2776                         leave_while = 1;
2777                         break;
2778                     }
2779
2780                     userlogstate = (DltUserControlMsgLogState*) (receiver->buf+sizeof(DltUserHeader));
2781                                         dlt_user.log_state = userlogstate->log_state;
2782
2783                                         /* keep not read data in buffer */
2784                                         if (dlt_receiver_remove(receiver,(sizeof(DltUserHeader)+sizeof(DltUserControlMsgLogState)))==-1)
2785                                         {
2786                                                 return -1;
2787                                         }
2788                 }
2789                 break;
2790                 default:
2791                 {
2792                     dlt_log(LOG_ERR,"Invalid user message type received!\n");
2793                     /* Ignore result */
2794                     dlt_receiver_remove(receiver,sizeof(DltUserHeader));
2795                                         /* In next invocation of while loop, a resync will be triggered if additional data was received */
2796                 }
2797                 break;
2798                 } /* switch() */
2799
2800                 if (leave_while==1)
2801                 {
2802                     leave_while=0;
2803                     break;
2804                 }
2805
2806             } /* while buffer*/
2807
2808             if (dlt_receiver_move_to_begin(receiver)==-1)
2809             {
2810                                 return -1;
2811             }
2812         } /* while receive */
2813     } /* if */
2814
2815     return DLT_RETURN_OK;
2816 }
2817
2818 int dlt_user_log_resend_buffer(void)
2819 {
2820         int num,count;
2821     uint8_t buf[DLT_USER_RCVBUF_MAX_SIZE];
2822     int size;
2823         DltReturnValue ret;
2824         
2825         /* Send content of ringbuffer */
2826         DLT_SEM_LOCK();
2827         count = dlt_buffer_get_message_count(&(dlt_user.startup_buffer));
2828         DLT_SEM_FREE();
2829
2830         for (num=0;num<count;num++)
2831         {
2832
2833                 DLT_SEM_LOCK();
2834                 size = dlt_buffer_copy(&(dlt_user.startup_buffer),buf,sizeof(buf));
2835
2836                 if (size>0)
2837                 {
2838 #ifdef DLT_SHM_ENABLE                                           
2839                         dlt_shm_push(&dlt_user.dlt_shm,buf+sizeof(DltUserHeader),size-sizeof(DltUserHeader),0,0,0,0);                   
2840
2841                         /* log to FIFO */
2842                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle, buf,sizeof(DltUserHeader),0,0,0,0);
2843 #else
2844                         /* log to FIFO */
2845                         ret = dlt_user_log_out3(dlt_user.dlt_log_handle, buf,size,0,0,0,0);
2846 #endif
2847
2848                         /* in case of error, keep message in ringbuffer */                        
2849                         if (ret==DLT_RETURN_OK)
2850                         {
2851                                 dlt_buffer_remove(&(dlt_user.startup_buffer));
2852                                 /*
2853                                 DLT_SEM_LOCK();
2854                                 if (dlt_buffer_push(&(dlt_user.startup_buffer), buf, size)==-1)
2855                                 {
2856                                         dlt_log(LOG_ERR,"Error pushing back message to history buffer. Message discarded.\n");
2857                                 }
2858                                 DLT_SEM_FREE();
2859
2860                                 // In case of: data could not be written, set overflow flag
2861                                 if (ret==DLT_RETURN_PIPE_FULL)
2862                                 {
2863                                         dlt_user.overflow = 1;
2864                                 }
2865                                 */
2866                         }
2867                         else
2868                         {
2869                                 /* keep message in ringbuffer */   
2870                                 DLT_SEM_FREE();
2871                                 return -1;
2872                         }
2873                 }
2874                 DLT_SEM_FREE();
2875         }
2876         
2877         return 0;
2878 }
2879
2880 void dlt_user_log_reattach_to_daemon(void)
2881 {
2882         uint32_t num,reregistered=0;
2883
2884         DltContext handle;
2885         DltContextData log_new;
2886
2887     if (dlt_user.dlt_log_handle<0)
2888     {
2889         dlt_user.dlt_log_handle=-1;
2890
2891         /* try to open pipe to dlt daemon */
2892         dlt_user.dlt_log_handle = open(DLT_USER_FIFO, O_WRONLY | O_NONBLOCK);
2893         if (dlt_user.dlt_log_handle > 0)
2894         {
2895             if (dlt_user_log_init(&handle,&log_new)==-1)
2896             {
2897                 return;
2898             }
2899
2900 #ifdef DLT_SHM_ENABLE
2901                         /* init shared memory */
2902                         if (dlt_shm_init_client(&dlt_user.dlt_shm,DLT_SHM_KEY) < 0)
2903                         {
2904                                 sprintf(str,"Loging disabled, Shared memory %d cannot be created!\n",DLT_SHM_KEY);
2905                                 dlt_log(LOG_WARNING, str);
2906                                 //return 0; 
2907                         }   
2908 #endif
2909
2910             dlt_log(LOG_NOTICE, "Logging re-enabled!\n");
2911
2912             /* Re-register application */
2913             if (dlt_user_log_send_register_application()==-1)
2914             {
2915                 return;
2916             }
2917
2918             DLT_SEM_LOCK();
2919
2920             /* Re-register all stored contexts */
2921             for (num=0; num<dlt_user.dlt_ll_ts_num_entries; num++)
2922             {
2923                 /* Re-register stored context */
2924                 if ((dlt_user.appID[0]!='\0') && (dlt_user.dlt_ll_ts[num].contextID[0]!='\0') && (dlt_user.dlt_ll_ts))
2925                 {
2926                     //dlt_set_id(log_new.appID, dlt_user.appID);
2927                     dlt_set_id(handle.contextID, dlt_user.dlt_ll_ts[num].contextID);
2928                     handle.log_level_pos = num;
2929                     log_new.context_description = dlt_user.dlt_ll_ts[num].context_description;
2930
2931                     log_new.log_level = DLT_USER_LOG_LEVEL_NOT_SET;
2932                     log_new.trace_status = DLT_USER_TRACE_STATUS_NOT_SET;
2933
2934                     if (dlt_user_log_send_register_context(&log_new)==-1)
2935                     {
2936                         DLT_SEM_FREE();
2937                         return;
2938                     }
2939
2940                     reregistered=1;
2941                 }
2942             }
2943
2944             DLT_SEM_FREE();
2945
2946             if (reregistered==1)
2947             {
2948                                 dlt_user_log_resend_buffer();
2949             }
2950         }
2951     }
2952 }
2953
2954 int dlt_user_log_send_overflow(void)
2955 {
2956     DltUserHeader userheader;
2957     DltReturnValue ret;
2958
2959     /* set userheader */
2960     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_OVERFLOW)==-1)
2961     {
2962         return -1;
2963     }
2964
2965     if (dlt_user.dlt_is_file)
2966     {
2967         return 0;
2968     }
2969
2970     /* log to FIFO */
2971     ret=dlt_user_log_out2(dlt_user.dlt_log_handle, &(userheader), sizeof(DltUserHeader), 0, 0);
2972     return ((ret==DLT_RETURN_OK)?0:-1);
2973 }
2974
2975 int dlt_user_check_buffer(int *total_size, int *used_size)
2976 {
2977 #ifdef DLT_SHM_ENABLE
2978         *total_size = dlt_shm_get_total_size(&(dlt_user.dlt_shm));
2979         *used_size = dlt_shm_get_used_size(&(dlt_user.dlt_shm));
2980 #else
2981         *total_size = dlt_buffer_get_total_size(&(dlt_user.startup_buffer));
2982         *used_size = dlt_buffer_get_used_size(&(dlt_user.startup_buffer));
2983 #endif
2984         
2985         return 0; /* ok */
2986 }
2987
2988 #ifdef DLT_TEST_ENABLE
2989 void dlt_user_test_corrupt_user_header(int enable)
2990 {
2991     dlt_user.corrupt_user_header = enable;
2992 }
2993 void dlt_user_test_corrupt_message_size(int enable,int16_t size)
2994 {
2995     dlt_user.corrupt_message_size = enable;
2996     dlt_user.corrupt_message_size_size = size;
2997 }
2998 #endif
2999
3000