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