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