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