BOROSOFTWAREAll work →
scantool/diag.h 444 lines
2 findings in this fileB6L274A4L275
1#ifndef _DIAG_H_
2#define _DIAG_H_
3
4/*
5 * freediag - Vehicle Diagnostic Utility
6 *
7 *
8 * Copyright (C) 2001 Richard Almeida & Ibex Ltd ([email protected])
9 * 2014-2015 fenugrec
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 *************************************************************************
26 *
27 * Library user header file
28 */
29
30#if defined(__cplusplus)
31extern "C" {
32#endif
33
34#include "cconf.h"
35
36#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37 #ifndef _WIN32_WINNT
38 #define _WIN32_WINNT 0x0500 //use > winXP features...
39 #endif
40 #include <time.h>
41 #include <basetsd.h>
42 #include <windows.h>
43#else
44 #include <sys/types.h>
45#endif
46
47#include <stdbool.h>
48#include <stdint.h> /* For uint8_t, etc. This is a C99 header */
49
50#if defined(_MSC_VER)
51//silence warnings about non-portable "_s" function replacements.
52//this must be set before including <stdio.h>.
53 #define _CRT_SECURE_NO_WARNINGS
54 #pragma warning(disable:4996)
55#endif /* _MSC_VER Visual Studio */
56#include <stdio.h> /* For FILE */
57
58#include "diag_os.h" //for mutexes...
59
60// Nice to have anywhere...
61#define MIN(_a_, _b_) (((_a_) < (_b_) ? (_a_) : (_b_)))
62#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
63#define FLFMT "%s:%d: " //for debug messages
64
65
66#ifdef HAVE_STRCASECMP
67 #include <strings.h>
68#else
69 #ifdef _WIN32
70//strcasecmp is POSIX, but kernel32 provides lstrcmpi which should be equivalent.
71 #define strcasecmp(a,b) lstrcmpi((LPCTSTR) a, (LPCTSTR) b)
72 #else
73 #error Your system provides no strcasecmp ! This is a problem !
74 #endif //WIN32
75#endif //HAVE_STRCASECMP
76
77
78#define DB_FILE "./freediag_carsim_all.db" //default simfile for CARSIM interface
79#define DIAG_NAMELEN 256
80
81
82/****** compiler-specific tweaks ******/
83#ifdef __GNUC__
84 #define UNUSED(X) X __attribute__((unused)) //magic !
85#else
86 #define UNUSED(X) X //how can we suppress "unused parameter" warnings on other compilers?
87#endif // __GNUC__
88
89//hacks for MS Visual studio / visual C
90#if defined(_MSC_VER)
91typedef SSIZE_T ssize_t; //XXX ssize_t is currently only needed because of diag_tty_unix.c:diag_tty_{read,write}.
92//TODO : rework read/write types to use a combination of size_t and int ?
93 #if _MSC_VER < 1910 /* anything older than Visual Studio 2017 */
94 #define snprintf _snprintf //danger : _snprintf doesn't guarantee zero-termination !?
95//as of Visual Studio 2015 the snprintf function is c99 compatible.
96//https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/snprintf-snprintf-snprintf-l-snwprintf-snwprintf-l?view=msvc-160
97 #pragma message("Warning: MSVC _sprintf() may be dangerous ! Please ask your compiler vendor to supply a C99-compliant snprintf()...")
98//CURFILE will be defined by CMake on a per-file basis !
99 #pragma message("Warning: MSVC may not work with the CURFILE macro. See diag.h")
100// apparently some (all ?) MSVC compilers don't support per-file defines, so CURFILE would be the
101// same for all source files.
102// The disadvantage of __FILE__ is that it often (always ?) holds the absolute path of the file,
103// not just the filename. For our debugging messages we only care about the filename, hence CURFILE.
104 #define FL __FILE__, __LINE__
105 #else
106// Using Visual Studio 2017 and higher the CURFILE macro will work.
107 #define FL CURFILE, __LINE__
108 #endif /* _MSC_VER < 1910 Visual Studio 2017 */
109#else
110 #define FL CURFILE, __LINE__
111#endif /* _MSC_VER Visual Studio */
112/****** ******/
113
114/*
115 * Many receive buffers are set to this, which is voluntarily larger than
116 * any possible valid message to/from an ECU.
117 */
118#define MAXRBUF 1024
119
120#define DIAG_MAX_MSGLEN 4200 /** limit diag_allocmsg() message size. */
121
122typedef uint8_t target_type, source_type, databyte_type, command_type;
123typedef uint16_t flag_type; //this is used for L2 type flags (see diag_l2.h)
124//only used for diag_l2_startcomms() arg
125
126/*
127 * IOCTLs
128 *
129 * The IOCTL can be done to any layer, and it is passed downward with
130 * each layer filling in info as needed (there are currently no clashes)
131 *
132 * Values for "cmd" parameter to diag_l[12]_ioctl()
133 * XXX Are their numeric values chosen on purpose ? i.e. why "2023" etc.
134 */
135
136#define DIAG_IOCTL_GET_L1_TYPE 0x2010 /* Get L1 Type, data is ptr to int */
137#define DIAG_IOCTL_GET_L1_FLAGS 0x2011 /* Get L1 Flags, data is ptr to int */
138#define DIAG_IOCTL_GET_L2_FLAGS 0x2021 /* Get the L2 flags (see fmt stuff )*/
139#define DIAG_IOCTL_GET_L2_DATA 0x2023 /* Get the L2 Keybytes etc into
140 * diag_l2_data passed to us
141 */
142#define DIAG_IOCTL_SETSPEED 0x2101 /* Set speed, bits etc. data = (const struct diag_serial_settings *); ret 0 if ok
143 * Ignored if DIAG_L1_AUTOSPEED or DIAG_L1_NOTTY is set */
144#define DIAG_IOCTL_INITBUS 0x2201 /* Initialise the ecu bus, data = (struct diag_l1_initbus_args *)
145 *
146 * Caller must have waited the appropriate time before calling this, since any
147 * bus-idle requirements are specified at the L2 level.
148 * Must return as soon as possible,
149 * and restore original port settings (speed, etc).
150 * See diag_l1.h for initbus args
151 * return 0 if ok
152 */
153#define DIAG_IOCTL_IFLUSH 0x2202 /* flush input buffers. No data. Ignored if DIAG_L1_NOTTY is set.
154 * Ret 0 if ok / not applicable (non fatal error) */
155/** Set wake-up (keepalive) message.
156 * Only applicable if DIAG_L1_DOESKEEPALIVE is set
157 *
158 * data = (struct diag_msg *).
159 * The (struct diag_msg)->data member must be a raw message (including headers)
160 *
161 * data can be freed by caller after the ioctl (L0 will make a copy of the message data as required)
162 */
163#define DIAG_IOCTL_SETWM 0x2203
164
165/****** debug control ******/
166// flag containers : diag_l0_debug, diag_l1_debug diag_l2_debug, diag_l3_debug, diag_cli_debug
167
168#define DIAG_DEBUG_OPEN 0x01 /* Open events */
169#define DIAG_DEBUG_CLOSE 0x02 /* Close events */
170#define DIAG_DEBUG_READ 0x04 /* Read events */
171#define DIAG_DEBUG_WRITE 0x08 /* Write events */
172#define DIAG_DEBUG_IOCTL 0x10 /* Ioctl stuff (setspeed etc) */
173#define DIAG_DEBUG_PROTO 0x20 /* Other protocol stuff */
174#define DIAG_DEBUG_INIT 0x40 /* Initialisation stuff */
175#define DIAG_DEBUG_DATA 0x80 /* Dump data depending on other flags */
176#define DIAG_DEBUG_TIMER 0x100 /* Timer stuff */
177
178
179// these are for identifying the debug message prefix to be printed
180enum debug_prefix {
181 DIAG_DEBUGPF_NONE,
182 DIAG_DEBUGPF_OPEN,
183 DIAG_DEBUGPF_CLOSE,
184 DIAG_DEBUGPF_READ,
185 DIAG_DEBUGPF_WRITE,
186 DIAG_DEBUGPF_IOCTL,
187 DIAG_DEBUGPF_PROTO,
188 DIAG_DEBUGPF_INIT,
189 DIAG_DEBUGPF_DATA,
190 DIAG_DEBUGPF_TIMER
191};
192
193/** debug message prefixes : dbg_prefixes[DIAG_DEBUGPF_XYZ] is a const char*
194 */
195extern const char *dbg_prefixes[];
196
197
198/**** debug message helpers.
199 *
200 * These macros will allow changing the backend and destination (stderr, file, etc)
201 *
202 */
203
204#define DIAG_DBGLEVEL_V 0
205
206/** for diag.h internal use only */
207#define DIAG_DBG_BACKEND(...) fprintf(stderr, __VA_ARGS__)
208
209
210/** print general debug message
211 *
212 */
213#define DIAG_DBGGEN(level, ...) DIAG_DBG_BACKEND(__VA_ARGS__);
214
215
216/** simple debug message formatter
217 *
218 * flagvar is the i.e. "diag_l1_debug" that is checked against mask.
219 * mask: see DIAG_DEBUG_* defs above
220 * level: not used yet
221 *
222 * Must be used for all non-essential messages. Does not add "\n"
223 *
224 */
225#define DIAG_DBGM(flagvar, mask, level, ...) do { \
226 if (((flagvar) & (mask)) == (mask)) { \
227 DIAG_DBG_BACKEND(__VA_ARGS__); \
228 }} while (0)
229
230/** debug message formatter with data
231 *
232 * flagvar is the i.e. "diag_l1_debug" that is checked against mask.
233 * mask: see DIAG_DEBUG_* defs above. No need to specify DIAG_DEBUG_DATA
234 * level: not used yet
235 *
236 * varargs: always printed. Automatically adds trailing "\n"
237 *
238 * Must be used for all non-essential messages.
239 *
240 */
241#define DIAG_DBGMDATA(flagvar, mask, level, data, datalen, ...) do { \
242 if (((flagvar) & (mask)) == (mask)) { \
243 DIAG_DBG_BACKEND(__VA_ARGS__); \
244 if ((flagvar) & DIAG_DEBUG_DATA) { \
245 diag_data_dump(stderr, data, datalen); \
246 } \
247 fprintf(stderr, "\n"); \
248 }} while (0)
249
250
251/*
252 * Message handling.
253 *
254 * These are messages passed to or from the layer 2 and layer 3 code
255 * which cause data to be transmitted to layer 1
256 *
257 * The receiver of the message *must* copy the data if it wants it !!!
258 * The flags are arranged such as zeroing out the whole structure sets "safe" defaults.
259 * There's probably no application for 0-length messages, but currently the various functions
260 * don't complain when allocating/duplicating empty data.
261 */
262struct diag_msg {
263 uint8_t fmt; /* Message format (doesn't absolutely need to be uint8_t) : */
264 #define DIAG_FMT_ISO_FUNCADDR 0x01 /* ISO Functional addressing (default : phys) */
265 #define DIAG_FMT_FRAMED 0x02 /* Rcvd data is framed, ie not raw. XXX DEPRECATED ! L0..L2 all do this.*/
266// #define DIAG_FMT_DATAONLY 0x04 /* Rcvd data had L2/L3 headers removed XXX ALWAYS ! */
267 #define DIAG_FMT_CKSUMMED 0x08 /* Someone (L1/L2) checked the checksum */
268 #define DIAG_FMT_BADCS 0x10 // message has bad checksum
269
270 uint8_t type; /* Type from received frame */
271 uint8_t dest; /* Destination from received frame */
272 uint8_t src; /* Source from received frame */
273
274 unsigned len; /* calculated data length */
275 uint8_t *data; /* The data; can be dynamically alloc'ed */
276
277 unsigned long rxtime; /* Processing timestamp, in ms given by diag_os_getms() */
278 struct diag_msg *next; /* For linked lists of messages */
279
280 uint8_t *idata; /* For free() of data later: this is a "backup"
281 * of the initial *data pointer.*/
282 uint8_t iflags; /* Internal flags */
283 #define DIAG_MSG_IFLAG_MALLOC 1 /* We malloced; we Free -- this is set when the msg
284 * was created by diag_allocmsg()*/
285};
286
287/** Allocate a new diag_msg
288 *
289 * Also allocates diag_msg-\>data if datalen\>0.
290 * @param datalen: if \>0, size of data buffer to allocate. Max DIAG_MAX_MSGLEN.
291 * @return new struct diag_msg, must be freed with diag_freemsg().
292 */
293struct diag_msg *diag_allocmsg(size_t datalen);
294/** Duplicate a diag_msg, including all chained messages and their contents.
295 * @return new struct diag_msg, must be freed with diag_freemsg().
296 */
297struct diag_msg *diag_dupmsg(struct diag_msg *);
298
299/** Duplicate a single diag_msg, without following the linked-list chain.
300 * @return new struct diag_msg, must be freed with diag_freemsg().
301 */
302struct diag_msg *diag_dupsinglemsg(struct diag_msg *);
303
304/** Free a diag_msg
305 * Safe to call with NULL arg
306 */
307void diag_freemsg(struct diag_msg *);
308
309/** Calculate 8bit checksum
310 * @param len: number of bytes in *data
311 * @return 8-bit sum of all bytes
312 */
313uint8_t diag_cks1(const uint8_t *data, unsigned int len);
314
315
316void diag_printmsg_header(FILE *fp, struct diag_msg *msg, bool timestamp, int msgnum);
317void diag_printmsg(FILE *fp, struct diag_msg *msg, bool timestamp);
318
319/*
320 * General functions
321 */
322//diag_init : ret 0 if ok;
323int diag_init(void);
324//diag_end : must be called before exiting. Ret 0 if ok
325int diag_end(void);
326
327/** Print bytes in hex format
328 * @param out: output stream (file / stderr / etc.)
329 * @param len: # of bytes to print
330 *
331 * Prints bytes with "0x%02X" formatter, e.g. "0x55 0xAA 0x03 "
332 */
333void diag_data_dump(FILE *out, const void *data, size_t len);
334
335//smartcat : only verifies if s1 is not too large !
336void smartcat(char *p1, const size_t s1, const char *p2 );
337
338/*
339 * Error functions.
340 * diag_p_* aren't intended to be called directly.
341 * Use "diag_pseterr" (returns a NULL pointer) or
342 * "diag_iseterr" (returns the passed in error code),
343 * which will save where the error took place and optionally log it.
344 */
345
346void *diag_p_pseterr(const char *name, const int line, const int code);
347int diag_p_iseterr(const char *name, const int line, const int code);
348void *diag_p_pfwderr(const char *name, const int line, const int code);
349int diag_p_ifwderr(const char *name, const int line, const int code);
350
351/** return NULL, set and print error. */
352#define diag_pseterr(C) diag_p_pseterr(CURFILE, __LINE__, (C))
353/** return (C), set and print error. */
354#define diag_iseterr(C) diag_p_iseterr(CURFILE, __LINE__, (C))
355
356/** return NULL, print error as a debug msg */
357#define diag_pfwderr(C) diag_p_pfwderr(CURFILE, __LINE__, (C))
358/** return (C), print error as a debug msg */
359#define diag_ifwderr(C) diag_p_ifwderr(CURFILE, __LINE__, (C))
360
361
362/** Return the last error and clears it.
363 */
364int diag_geterr(void);
365
366/** Get textual description of error
367 *
368 * Note, it returns a pointer to a statically allocated buffer
369 * common to all threads and that must not be free'd.
370 */
371const char *diag_errlookup(const int code);
372
373/*
374 * "calloc" and "malloc" that log errors when they fail.
375 * As with the seterr functions, only "diag_calloc" and "diag_malloc"
376 * are intended to be called directly.
377 *
378 */
379
380// Do not call directly.
381int diag_fl_alloc(const char *fName, const int line,
382 void **pp, size_t n, size_t s, bool allocIsCalloc);
383
384/** calloc() with logging (clears data)
385 * @param P: *ptr
386 * @param N: number of (sizeof) elems to allocate
387 * @return 0 if OK
388 * @note there is no size argument - it gets it directly
389 * using sizeof. This makes it a little unusual, but reduces potential errors.
390 */
391#define diag_calloc(P, N) diag_fl_alloc(CURFILE, __LINE__, \
392 ((void **)(P)), (N), sizeof(**(P)), true)
393
394/** malloc() with logging.
395 * @return 0 if OK
396 * Same as diag_calloc, but without clearing.
397 */
398#define diag_malloc(P, N) diag_fl_alloc(CURFILE, __LINE__, \
399 ((void **)(P)), (N), sizeof(**(P)), false)
400
401/** Add a string to array-of-strings (argv style)
402 * @param elems: number of elements already in table
403 * @return new table ptr, NULL if failed
404 */
405char **strlist_add(char **list, const char *news, int elems);
406
407/** Free argv-style string list
408 * @param elems: number of strings in list
409 */
410void strlist_free(char **slist, int elems);
411
412// Atomics
413
414// Atomically accessed types
415typedef struct {
416 diag_mtx mtx;
417 bool v;
418} diag_atomic_bool;
419typedef struct {
420 diag_mtx mtx;
421 int v;
422} diag_atomic_int;
423
424#define diag_atomic_init(V) diag_os_initstaticmtx(&((V)->mtx))
425#define diag_atomic_del(V) diag_os_delmtx(&((V)->mtx))
426
427void diag_atomic_store_bool(diag_atomic_bool *a, bool d);
428void diag_atomic_store_int(diag_atomic_int *a, int d);
429bool diag_atomic_load_bool(diag_atomic_bool *a);
430int diag_atomic_load_int(diag_atomic_int *a);
431
432/** Check if periodic timers have finished
433 *
434 * Returns true if the periodic timer is no longer necessary, ie. if the diag_end has been
435 * run. Returns false otherwise.
436 */
437bool periodic_done(void);
438
439#if defined(__cplusplus)
440}
441#endif
442
443#endif /* _DIAG_H_ */
444