diff --git a/.gitignore b/.gitignore index 459a2a9..511a718 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,14 @@ Utilities/can_moni/Release Utilities/can_moni/can_moni Utilities/can_moni/*.sln Utilities/can_moni/*.vcxproj.user +Utilities/can_send/.vs +Utilities/can_send/x64 +Utilities/can_send/x86 +Utilities/can_send/Debug +Utilities/can_send/Release +Utilities/can_send/can_send +Utilities/can_send/*.sln +Utilities/can_send/*.vcxproj.user Utilities/can_test/.vs Utilities/can_test/x64 Utilities/can_test/x86 diff --git a/Deployment.md b/Deployment.md index b93da86..771d9d3 100644 --- a/Deployment.md +++ b/Deployment.md @@ -17,23 +17,22 @@ _All rights reserved._ from PEAK's website and commit it with commit comment: - `Update PEAK's PCANBasic DLL (version `_n_`.`_n_`.`_n_`)` \ `- `_list of major changes (optional)_ -2. If necessary, update the CAN API V3 sources in `$(PROJROOT)\Sources\CANAPI` +1. If necessary, update the CAN API V3 sources in `$(PROJROOT)\Sources\CANAPI` from the SVN repo and commit them with commit comment: - `Update CAN API V3 sources to rev. `_nnn_ \ `- `_list of major changes (optional)_ -3. If necessary, update the CAN API V3 testing sources in `$(PROJROOT)\Tests` +1. If necessary, update the CAN API V3 testing sources in `$(PROJROOT)\Tests` from the SVN repo and commit them with commit comment: - `Update CAN API V3 testing sources to rev. `_nnn_ \ `- `_list of major changes (optional)_ -4. Check and update the version and date information in the following files: +1. Check and update the version and date information in the following files: - `$(PROJROOT)\Sources\Version.h` - - `$(PROJROOT)\Sources\PeakCAN.h` - - `$(PROJROOT)\Sources\PeakCAN.cpp` - - `$(PROJROOT)\Sources\Wrapper\can_api.c` - `$(PROJROOT)\Libraries\CANAPI\uvcanpcb.rc` - `$(PROJROOT)\Libraries\PeakCAN\PeakCAN.rc` - - `$(PROJROOT)\Utilities\can_moni\Driver.h` - - `$(PROJROOT)\Utilities\can_test\Driver.h` + - `$(PROJROOT)/Utilities/can_moni/README.md` + - `$(PROJROOT)/Utilities/can_port/README.md` + - `$(PROJROOT)/Utilities/can_send/README.md` + - `$(PROJROOT)/Utilities/can_test/README.md` ### Procedure @@ -43,7 +42,7 @@ _All rights reserved._ 2. Open the trial program with Visual Studio and run a code analysis. - _**There should not be any serious finding.**_ - _If there are findings then fix them or create an issue in the repo._ -3. Run `x86_build.bat` and `x64_build.bat` in the project root directory. +3. Run `x64_build.bat` in the project root directory. - _**There should be absolutely no compiler or linker error!**_ - _If there are compiler or linker warnings then think twice._ 4. Try out the trial program with different options. @@ -71,16 +70,13 @@ _All rights reserved._ 2. Double check all version numbers again (see above). 3. Run the batch files in the project root directory: - `C:\Users\haumea>cd C:\Projects\CAN\Drivers\PeakCAN` - - `C:\Projects\CAN\Drivers\PeakCAN>x86_build.bat` - - `C:\Projects\CAN\Drivers\PeakCAN>x86_install.bat` - `C:\Projects\CAN\Drivers\PeakCAN>x64_build.bat` - `C:\Projects\CAN\Drivers\PeakCAN>x64_install.bat` 4. Build the CAN API V3 GoogleTest program: - `C:\Users\haumea>cd C:\Projects\CAN\Drivers\PeakCAN\Tests` - - `C:\Projects\CAN\Drivers\PeakCAN\Tests>x86_build.bat` - `C:\Projects\CAN\Drivers\PeakCAN\Tests>x64_build.bat` 5. Run the CAN API V3 GoogleTest program with two PCAN-USB devices in CAN 2.0 mode: - - `C:\Projects\CAN\Drivers\PeakCAN\Tests>Debug\pcb_testing --can_dut1=PCAN-USB1 --can_dut2=PCAN-USB2 --can_mode=2.0 --can_bitrate=DEFAULT --gtest_output=xml:TestReport_PCAN-USB.xml --run_all=YES --smoketest_frames=100000` [...] + - `C:\Projects\CAN\Drivers\PeakCAN\Tests>x64\Debug\pcb_testing --can_dut1=PCAN-USB1 --can_dut2=PCAN-USB2 --can_mode=2.0 --can_bitrate=DEFAULT --gtest_output=xml:TestReport_PCAN-USB.xml --run_all=YES --smoketest_frames=100000` [...] - _If there is any error then **stop** here or create an issue for each error in the repo._ - Copy the test report into the binary's directory `$(PROJROOT)\Binaries`. 6. Run the CAN API V3 GoogleTest program with two PCAN-USB FD devices in CAN FD mode: @@ -98,7 +94,7 @@ _All rights reserved._ 1. Click on `Draft a new release` in the [GitHub](https://github.com/uv-software/PeakCAN-Wrapper) repo. 2. Fill out all required fields: - - Tag version: e.g `v0.5` (cf. semantic versioning) + - Tag version: e.g `v0.6` (cf. semantic versioning) - Target: `main` (default branch) - Release title: e.g. `Release of January 19, 2038` - Change-log: list all major changes, e.g. from commit comments diff --git a/Examples/C++/can_recv.cpp b/Examples/C++/can_recv.cpp index e1f9910..2334a97 100644 --- a/Examples/C++/can_recv.cpp +++ b/Examples/C++/can_recv.cpp @@ -54,16 +54,22 @@ int main(/*int argc, const char * argv[]*/) { std::cerr << "+++ error: interface could not be started" << std::endl; goto teardown; } - std::cout << "Press Ctrl+C to abort..." << std::endl; + std::cout << "Press ^C to abort." << std::endl; while (running) { if ((retVal = myDriver.ReadMessage(message, CANREAD_INFINITE)) == CCanApi::NoError) { fprintf(stdout, "%i\t", frames++); fprintf(stdout, "%7li.%04li\t", (long)message.timestamp.tv_sec, message.timestamp.tv_nsec / 100000); - if (!opMode.fdoe) - fprintf(stdout, "%03X\t%c%c [%u] ", message.id, message.xtd ? 'X' : 'S', message.rtr ? 'R' : ' ', message.dlc); - else - fprintf(stdout, "%03X\t%c%c%c%c%c [%u] ", message.id, message.xtd ? 'X' : 'S', message.rtr ? 'R' : ' ', - message.fdf ? 'F' : ' ', message.brs ? 'B' : ' ', message.esi ? 'E' :' ', CCanApi::Dlc2Len(message.dlc)); + fprintf(stdout, "%03X\t", message.id); + if (!message.sts) { + fputc(message.xtd ? 'X' : 'S', stdout); + fputc(message.fdf ? 'F' : '-', stdout); + fputc(message.brs ? 'B' : '-', stdout); + fputc(message.esi ? 'E' : '-', stdout); + fputc(message.rtr ? 'R' : '-', stdout); + } else { + fprintf(stdout, "Error"); + } + printf(" [%u]", CCanApi::Dlc2Len(message.dlc)); for (uint8_t i = 0; i < CCanApi::Dlc2Len(message.dlc); i++) fprintf(stdout, " %02X", message.data[i]); if (message.sts) diff --git a/Examples/Python/CANAPI.py b/Examples/Python/CANAPI.py index 30aec69..5578fb9 100644 --- a/Examples/Python/CANAPI.py +++ b/Examples/Python/CANAPI.py @@ -2,8 +2,9 @@ # # CAN Interface API, Version 3 (Python Wrapper) # -# Copyright (c) 2005-2025 Uwe Vogt, UV Software, Berlin (info@uv-software.com) -# All rights reserved. +# Copyright (c) 2005-2012 Uwe Vogt, UV Software, Friedrichshafen +# Copyright (c) 2013-2025 Uwe Vogt, UV Software, Berlin (info@uv-software.com) +# All rights reserved. # # This file is part of CAN API V3. # @@ -21,7 +22,7 @@ # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # -# CAN API V3 IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS +# CAN API V3 IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE @@ -54,9 +55,9 @@ Interface API for various CAN interfaces from different vendors running under multiple operating systems. - $Author: quaoar $ + $Author: makemake $ - $Rev: 1408 $ + $Rev: 1416 $ """ from ctypes import * import platform @@ -71,7 +72,7 @@ # CAN API V3 - Python Wrapper # -CAN_API_V3_PYTHON = {'major': 0, 'minor': 3, 'patch': 1} +CAN_API_V3_PYTHON = {'major': 0, 'minor': 3, 'patch': 2} # CAN Identifier Ranges # diff --git a/README.md b/README.md index 02d9f41..6239096 100644 --- a/README.md +++ b/README.md @@ -83,30 +83,35 @@ C:\Projects\CAN\Drivers\PeakCAN>build_no.bat ``` Repeat this step after each `git commit`, `git pull`, `git clone`, etc. -To build all 32-bit targets (x86) run the script `x86_build.bat`. -``` -C:\Users\haumea>cd C:\Projects\CAN\Drivers\PeakCAN -C:\Projects\CAN\Drivers\PeakCAN>x86_build.bat -``` - -To build all 64-bit targets (x64) run the script `x64_build.bat`. +To build all targets (x64) run the script `x64_build.bat`. ``` C:\Users\haumea>cd C:\Projects\CAN\Drivers\PeakCAN C:\Projects\CAN\Drivers\PeakCAN>x64_build.bat ``` (The version number of the libraries can be adapted by editing the `.rc` files in the corresponding subfolders. Don´t forget to set the version number also in the header file `Version.h`.) -#### uvPeakCAN (DLL) +#### Libraries + +##### uvPeakCAN (DLL) ___uvPeakCAN___ is a dynamic link library with a CAN API V3 compatible application programming interface for use in __C++__ applications. See header file `PeakCAN.h` for a description of all class members. -#### u3canpcb (DLL) +##### u3canpcb (DLL) ___u3canpcb___ is a dynamic link library with a CAN API V3 compatible application programming interface for use in __C__ applications. See header file `can_api.h` for a description of all API functions. -#### can_moni (CLI) +#### Utilities + +##### can_send + +`can_send` is a command line tool to send CAN messages that are entered at the program prompt. +The syntax is taken from the Linux SocketCAN utility [can_utils\cansend](https://github.com/linux-can/can-utils/tree/master). + +Type `can_send /?` to display all program options. + +##### can_moni (CLI) `can_moni` is a command line tool to view incoming CAN messages. I hate this messing around with binary masks for identifier filtering. @@ -114,7 +119,7 @@ So I wrote this little program to have an exclude list for single identifiers or Type `can_moni /?` to display all program options. -#### can_test (CLI) +##### can_test (CLI) `can_test` is a command line tool to test CAN communication. Originally developed for electronic environmental tests on an embedded Linux system with SocketCAN, I´m using it for many years as a traffic generator for CAN stress-tests. @@ -127,7 +132,7 @@ Type `can_test /?` to display all program options. ### Development Environment -- Microsoft Visual Studio Community 2022 (Version 17.12.4) +- Microsoft Visual Studio Community 2022 (Version 17.13.2) ### Required PCANBasic DLL @@ -168,7 +173,7 @@ You can choose between one of them if you use these portions of this work in who Windows is a registered trademark of Microsoft Corporation in the United States and/or other countries. \ PCAN is a registered trademark of PEAK-System Technik GmbH, Darmstadt, Germany. \ -Mac and macOS are trademarks of Apple Inc., registered in the U.S. and other countries. \ +Mac and macOS are trademarks of Apple Inc., registered in the U.S. and other countries and regions. \ Linux is a registered trademark of Linus Torvalds. \ All other company, product and service names mentioned herein may be trademarks, registered trademarks, or service marks of their respective owners. diff --git a/Sources/CANAPI/.gitignore b/Sources/CANAPI/.gitignore index cfaf4b6..21d8bf0 100644 --- a/Sources/CANAPI/.gitignore +++ b/Sources/CANAPI/.gitignore @@ -1,6 +1,4 @@ .svn -# Not realized yet -CANIPC_Message.h # we don't use the JSON files yet can_dev.? vanilla.? @@ -8,3 +6,4 @@ vanilla.? SerialCAN_Defines.h SocketCAN_Defines.h RocketCAN_Defines.h +CANIPC_Message.h diff --git a/Sources/CANAPI/CANAPI_Version.h b/Sources/CANAPI/CANAPI_Version.h index 4b43b95..1a5bfee 100644 --- a/Sources/CANAPI/CANAPI_Version.h +++ b/Sources/CANAPI/CANAPI_Version.h @@ -53,17 +53,17 @@ * * @note This is only a dummy file to have a SVN revision number. * - * @author $Author: makemake $ + * @author $Author: quaoar $ * - * @version $Rev: 1407 $ + * @version $Rev: 1467 $ * * @addtogroup can_api * @{ */ #ifndef CANAPI_VERSION_H_INCLUDED #define CANAPI_VERSION_H_INCLUDED -// SVN revision number (update with each commit: III) -#define CAN_API_REV "$Rev: 1407 $" +// SVN revision number (update with each commit: VI) +#define CAN_API_REV "$Rev: 1467 $" #endif /* CANAPI_VERSION_H_INCLUDED */ /** @} */ diff --git a/Sources/CANAPI/can_msg.c b/Sources/CANAPI/can_msg.c index 6cf08e3..6025434 100644 --- a/Sources/CANAPI/can_msg.c +++ b/Sources/CANAPI/can_msg.c @@ -51,9 +51,9 @@ * * @brief CAN Message Formatter * - * @author $Author: makemake $ + * @author $Author: quaoar $ * - * @version $Rev: 1407 $ + * @version $Rev: 1467 $ * * @addtogroup can_msg * @{ @@ -102,6 +102,17 @@ ((x) > 12U) ? 0xAU : \ ((x) > 8U) ? 0x9U : (x) #endif +#define IS_EOL(c) (((c) == '\0') || ((c) == '\n') || ((c) == '\r')) +#define IS_HEX(c) (isdigit(c) || (((c) >= 'A') && ((c) <= 'F')) || (((c) >= 'a') && ((c) <= 'f'))) +#define IS_DIGIT(c) (isdigit(c)) +#define IS_SPACE(c) (isspace(c)) +#define CHR2DEC(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : 0xFF) +#define CHR2HEX(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : \ + (c) >= 'a' && (c) <= 'f' ? (c) - 'a' + 10 : \ + (c) >= 'A' && (c) <= 'F' ? (c) - 'A' + 10 : 0xFF) +#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ +#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */ +#define CANFD_FDF 0x04 /* mark CAN FD for dual use of struct canfd_frame */ /* ----------- types -------------------------------------------------- @@ -685,6 +696,149 @@ int msg_set_fmt_tx_prompt(const char *option) return rc; } +/* parser: SocketCAN ASCII format (see 'can_utils/cansend') */ +int msg_parse(const char *str, msg_message_t *msg, uint32_t *cnt, uint64_t *cyc, int *inc) { + unsigned long can_id = 0x000U; + const char *ptr = str; + char *endptr; + + memset(msg, 0, sizeof(msg_message_t)); + *cnt = 1; + *cyc = 0; + *inc = 0; + + /* sanity check */ + if (!str || !msg || !cnt || !cyc || !inc) { + return -1; + } + + /* parse CAN identifier */ + can_id = strtoul(ptr, &endptr, 16); + if ((endptr == ptr) || (((endptr - ptr) != 3) && ((endptr - ptr) != 8))) { + return -1; + } + if ((endptr - ptr) == 8) { + msg->xtd = 1; + } + if ((uint32_t)can_id > (uint32_t)(msg->xtd ? CAN_MAX_XTD_ID : CAN_MAX_STD_ID)) { + return -1; + } + msg->id = (uint32_t)can_id; + ptr = endptr; + + /* parse frame type */ + if (*ptr != '#') { + return -1; + } + ptr++; + + /* parse CAN FD flags if present */ + if (*ptr == '#') { + ptr++; + if (!IS_HEX(*ptr)) { + return -1; + } + /* map CAN FD flags */ + char flags = CHR2HEX(*ptr); + if ((flags & ~(CANFD_BRS | CANFD_ESI)) != CANFD_FDF) { + return -1; + } + msg->fdf = (flags & CANFD_FDF) ? 1 : 0; + msg->brs = (flags & CANFD_BRS) ? 1 : 0; + msg->esi = (flags & CANFD_ESI) ? 1 : 0; + ptr++; + /* not sure if this is also in linux/can_utils */ + if (*ptr == '.') ptr++; + } + + /* parse data or remote frame */ + if (*ptr == 'R') { + msg->rtr = 1; + ptr++; + /* parse optional DLC */ + if (IS_DIGIT(*ptr)) { + msg->dlc = (uint8_t)CHR2DEC(*ptr); + if (msg->dlc > CAN_MAX_DLC) return -1; + ptr++; + } + } else { + uint8_t len = 0; + /* parse data (max. 8 bytes resp. 64 bytes for CAN FD) */ + while (!IS_EOL(*ptr) && IS_HEX(*ptr)) { + if (len >= (msg->fdf ? CANFD_MAX_LEN : CAN_MAX_LEN)) return -1; + if (!IS_HEX(*(ptr + 1))) return -1; // Ensure there are two hex digits + char hex_byte[3] = { *ptr, *(ptr + 1), '\0' }; // Create a string with two hex digits + msg->data[len++] = (uint8_t)strtol(hex_byte, NULL, 16); + ptr += 2; // Move to the next pair of hex digits + if (*ptr == '.') ptr++; // Skip the '.' separator + } + if (*ptr == '.') return -1; + /* convert data length to DLC */ + msg->dlc = (uint8_t)LEN2DLC(len); + } + + /* parse optional DLC ('9' .. 'F') */ + if (!msg->fdf && (*ptr == '_')) { + ptr++; + if (!IS_HEX(*ptr)) return -1; + if (CHR2DEC(*ptr) <= CAN_MAX_DLC) return -1; + /* ignore extra DLC */ + ptr++; + } + + /* parse optional transmission options */ + if ((*ptr == 'x') || (*ptr == 'X') || (*ptr == '*')) { + ptr++; + /* number of messages to send */ + if (!IS_DIGIT(*ptr)) return -1; + long count = strtoul(ptr, &endptr, 10); + if ((endptr == ptr) || (count <= 0) || (count > UINT32_MAX)) return -1; + *cnt = (uint32_t)count; + ptr = endptr; + /* cycle time (in [ms]) */ + if ((*ptr == 'C') || (*ptr == 'c')) { + ptr++; + if (!IS_DIGIT(*ptr)) return -1; + long msec = strtoul(ptr, &endptr, 10); + if ((endptr == ptr) || (msec < 0L) || (msec > 60000L)) return -1; + *cyc = (uint64_t)(msec * 1000); + ptr = endptr; + } + /* cycle time (in [us]) */ + else if ((*ptr == 'U') || (*ptr == 'u')) { + ptr++; + if (!IS_DIGIT(*ptr)) return -1; + long usec = strtoul(ptr, &endptr, 10); + if ((endptr == ptr) || (usec < 0L) || (usec > 60000000L)) return -1; + *cyc = (uint64_t)usec; + ptr = endptr; + } + /* upcounting data */ + if (*ptr == '+') { + if (*(ptr + 1) == '+') { + *inc = 1; + ptr += 2; + } else { + return -1; + } + } + /* downcounting data */ + else if (*ptr == '-') { + if (*(ptr + 1) == '-') { + *inc = -1; + ptr += 2; + } else { + return -1; + } + } + } + /* check end of string */ + if (!IS_EOL(*ptr) && !IS_SPACE(*ptr)) { + return -1; + } + return 0; +} + /* ----------- local functions ---------------------------------------- */ diff --git a/Sources/CANAPI/can_msg.h b/Sources/CANAPI/can_msg.h index 0674e44..351fa9b 100644 --- a/Sources/CANAPI/can_msg.h +++ b/Sources/CANAPI/can_msg.h @@ -51,9 +51,9 @@ * * @brief CAN Message Formatter * - * @author $Author: makemake $ + * @author $Author: sedna $ * - * @version $Rev: 1407 $ + * @version $Rev: 1458 $ * * @defgroup can_msg CAN Message Formatter * @{ @@ -290,62 +290,62 @@ typedef enum msg_direction_t_ { /* ----------- prototypes --------------------------------------------- */ -/** @brief ... +/** @brief Returns the given CAN API V3 message as a formatted string. * - * @param[in] message - ... + * @param[in] message CAN API V3 messge * - * @returns pointer to a zero-terminated string. + * @returns pointer to a zero-terminated string, or NULL on error. */ -char *msg_format_message(const msg_message_t *message, msg_direction_t direction, - msg_counter_t counter, msg_channel_t channel); +extern char *msg_format_message(const msg_message_t *message, msg_direction_t direction, + msg_counter_t counter, msg_channel_t channel); -/** @brief ... +/** @brief Returns the time-stamp of a CAN API V3 message as a formatted string. * - * @param[in] message - ... + * @param[in] message CAN API V3 messge * - * @returns pointer to a zero-terminated string. + * @returns pointer to a zero-terminated string, or NULL on error. */ -char *msg_format_time(const msg_message_t *message); +extern char *msg_format_time(const msg_message_t *message); -/** @brief ... +/** @brief Returns the idnetifier of a CAN API V3 message as a formatted string. * - * @param[in] message - ... + * @param[in] message CAN API V3 messge * - * @returns pointer to a zero-terminated string. + * @returns pointer to a zero-terminated string, or NULL on error. */ -char *msg_format_id(const msg_message_t *message); +extern char *msg_format_id(const msg_message_t *message); -/** @brief ... +/** @brief Returns the flags of a CAN API V3 message as a formatted string. * - * @param[in] message - ... + * @param[in] message CAN API V3 messge * - * @returns pointer to a zero-terminated string. + * @returns pointer to a zero-terminated string, or NULL on error. */ -char *msg_format_flags(const msg_message_t *message); +extern char *msg_format_flags(const msg_message_t *message); -/** @brief ... +/** @brief Returns the data length code of a CAN API V3 message as a formatted string. * - * @param[in] message - ... + * @param[in] message CAN API V3 messge * - * @returns pointer to a zero-terminated string. + * @returns pointer to a zero-terminated string, or NULL on error. */ -char *msg_format_dlc(const msg_message_t *message); +extern char *msg_format_dlc(const msg_message_t *message); -/** @brief ... +/** @brief Returns the data of a CAN API V3 message as a formatted string (binary representation). * - * @param[in] message - ... + * @param[in] message CAN API V3 messge * - * @returns pointer to a zero-terminated string. + * @returns pointer to a zero-terminated string, or NULL on error. */ -char *msg_format_data(const msg_message_t *message); +extern char *msg_format_data(const msg_message_t *message); -/** @brief ... +/** @brief Returns the data of a CAN API V3 message as a formatted string (ASCII representation). * - * @param[in] message - ... + * @param[in] message CAN API V3 messge * - * @returns pointer to a zero-terminated string. + * @returns pointer to a zero-terminated string, or NULL on error. */ -char *msg_format_ascii(const msg_message_t *message); +extern char *msg_format_ascii(const msg_message_t *message); /** @brief set message output format {DEFAULT, ...}. * @@ -353,7 +353,7 @@ char *msg_format_ascii(const msg_message_t *message); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_format(msg_format_t format); +extern int msg_set_format(msg_format_t format); /** @brief set formatter option: time-stamp {ZERO, ABS, REL}. * @@ -361,7 +361,7 @@ int msg_set_format(msg_format_t format); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_time_stamp(msg_fmt_timestamp_t option); +extern int msg_set_fmt_time_stamp(msg_fmt_timestamp_t option); /** @brief set formatter option: time-stamp in usec {OFF, ON}. * @@ -369,7 +369,7 @@ int msg_set_fmt_time_stamp(msg_fmt_timestamp_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_time_usec(msg_fmt_option_t option); +extern int msg_set_fmt_time_usec(msg_fmt_option_t option); /** @brief set formatter option: time format {TIME, SEC, DJD}. * @@ -377,7 +377,7 @@ int msg_set_fmt_time_usec(msg_fmt_option_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_time_format(msg_fmt_time_t option); +extern int msg_set_fmt_time_format(msg_fmt_time_t option); /** @brief set formatter option: identifier {HEX, DEC, OCT, BIN}. * @@ -385,7 +385,7 @@ int msg_set_fmt_time_format(msg_fmt_time_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_id(msg_fmt_number_t option); +extern int msg_set_fmt_id(msg_fmt_number_t option); /** @brief set formatter option: extended identifier {OFF, ON}. * @@ -393,7 +393,7 @@ int msg_set_fmt_id(msg_fmt_number_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_id_xtd(msg_fmt_option_t option); +extern int msg_set_fmt_id_xtd(msg_fmt_option_t option); /** @brief set formatter option: DLC/length {HEX, DEC, OCT, BIN}. * @@ -401,7 +401,7 @@ int msg_set_fmt_id_xtd(msg_fmt_option_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_dlc(msg_fmt_number_t option); +extern int msg_set_fmt_dlc(msg_fmt_number_t option); /** @brief set formatter option: CAN FD format {DLC, LENGTH}. * @@ -409,7 +409,7 @@ int msg_set_fmt_dlc(msg_fmt_number_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_dlc_format(msg_fmt_canfd_t option); +extern int msg_set_fmt_dlc_format(msg_fmt_canfd_t option); /** @brief set formatter option: DLC in brackets {'\0', '(', '['}. * @@ -417,7 +417,7 @@ int msg_set_fmt_dlc_format(msg_fmt_canfd_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_dlc_brackets(int option); +extern int msg_set_fmt_dlc_brackets(int option); /** @brief set formatter option: message flags {ON, OFF}. * @@ -425,7 +425,7 @@ int msg_set_fmt_dlc_brackets(int option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_flags(msg_fmt_option_t option); +extern int msg_set_fmt_flags(msg_fmt_option_t option); /** @brief set formatter option: message data {HEX, DEC, OCT, BIN}. * @@ -433,7 +433,7 @@ int msg_set_fmt_flags(msg_fmt_option_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_data(msg_fmt_number_t option); +extern int msg_set_fmt_data(msg_fmt_number_t option); /** @brief set formatter option: data as ASCII {ON, OFF}. * @@ -441,7 +441,7 @@ int msg_set_fmt_data(msg_fmt_number_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_ascii(msg_fmt_option_t option); +extern int msg_set_fmt_ascii(msg_fmt_option_t option); /** @brief set formatter option: substitute for non-printable characters. * @@ -449,7 +449,7 @@ int msg_set_fmt_ascii(msg_fmt_option_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_ascii_subst(int option); +extern int msg_set_fmt_ascii_subst(int option); /** @brief set formatter option: message source {OFF, ON}. * @@ -457,7 +457,7 @@ int msg_set_fmt_ascii_subst(int option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_channel(msg_fmt_option_t option); +extern int msg_set_fmt_channel(msg_fmt_option_t option); /** @brief set formatter option: message counter {ON, OFF}. * @@ -465,7 +465,7 @@ int msg_set_fmt_channel(msg_fmt_option_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_counter(msg_fmt_option_t option); +extern int msg_set_fmt_counter(msg_fmt_option_t option); /** @brief set formatter option: separator {SPACES, TABS}. * @@ -473,7 +473,7 @@ int msg_set_fmt_counter(msg_fmt_option_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_separator(msg_fmt_separator_t option); +extern int msg_set_fmt_separator(msg_fmt_separator_t option); /** @brief set formatter option: wraparound {NO, 8, 16, 32, 64}. * @@ -481,7 +481,7 @@ int msg_set_fmt_separator(msg_fmt_separator_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_wraparound(msg_fmt_wraparound_t option); +extern int msg_set_fmt_wraparound(msg_fmt_wraparound_t option); /** @brief set formatter option: end-of-line character {OFF, ON}. * @@ -489,7 +489,7 @@ int msg_set_fmt_wraparound(msg_fmt_wraparound_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_eol(msg_fmt_option_t option); +extern int msg_set_fmt_eol(msg_fmt_option_t option); /** @brief set formatter option: prompt for received messages (char[6+1]). * @@ -497,7 +497,7 @@ int msg_set_fmt_eol(msg_fmt_option_t option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_rx_prompt(const char *option); +extern int msg_set_fmt_rx_prompt(const char *option); /** @brief set formatter option: prompt for sent messages (char[6+1]). * @@ -505,7 +505,47 @@ int msg_set_fmt_rx_prompt(const char *option); * * @returns non-zero value on success, otherwise 0. */ -int msg_set_fmt_tx_prompt(const char *option); +extern int msg_set_fmt_tx_prompt(const char *option); + +/** @brief Parse CAN API V3 message from ASCII string. + * + * The syntax is taken from 'cansend' utility of the Linux SocketCAN package. + * + * : + * #{data} for CAN CC data frames + * #R{len} for CAN CC remote frames + * #{data}_{dlc} for CAN CC data frames with 9..F DLC + * #R{len}_{dlc} for CAN CC remote frames with 9..F DLC + * ##{data} for CAN FD data frames (up to 64 bytes) + * + * : + * 3 (SFF) or 8 (EFF) hex characters + * {data}: + * 0..8 (0..64 CAN FD) ASCII hex-values (optionally separated by '.') + * {len}: + * an optional 0..8 value as RTR frames can contain a valid dlc field + * _{dlc}: + * an optional 9..F data length code value when payload length is 8 + * : + * a single ASCII Hex value (0 .. F) which defines CAN FD flags: + * 0x4: FDF (CAN FD frame) + * 0x1: BRS (Bit Rate Switch) + * 0x2: ESI (Error State Indicator) + * Valid combinations are: + * 0x4: FDF + * 0x5: FDF and BRS + * 0x6: FDF and ESI + * 0x7: FDF, BRS and ESI + * + * @param[in] str ASCII string + * @param[out] msg CAN API V3 message + * @param[out] cnt count (default: 1) + * @param[out] cyc cycle time (in [us]) + * @param[out] inc increment: 0 = none, 1 = increment, -1 = decrement + * + * @return 0 on success, -1 on error + */ +extern int msg_parse(const char *str, msg_message_t *msg, uint32_t *cnt, uint64_t *cyc, int *inc); #ifdef __cplusplus diff --git a/Sources/PeakCAN.h b/Sources/PeakCAN.h index 4948283..4f9510c 100644 --- a/Sources/PeakCAN.h +++ b/Sources/PeakCAN.h @@ -179,6 +179,7 @@ class CANCPP CPeakCAN : public CCanApi { //#define PEAKCAN_PROPERTY_TRM_QUEUE_HIGH (CANPROP_GET_TRM_QUEUE_HIGH) //#define PEAKCAN_PROPERTY_TRM_QUEUE_OVFL (CANPROP_GET_TRM_QUEUE_OVFL) #define PEAKCAN_PROPERTY_DEVICE_ID (CANPROP_GET_VENDOR_PROP + PCAN_DEVICE_ID) +#define PEAKCAN_PROPERTY_DEVICE_GUID (CANPROP_GET_VENDOR_PROP + PCAN_DEVICE_GUID) #define PEAKCAN_PROPERTY_API_VERSION (CANPROP_GET_VENDOR_PROP + PCAN_API_VERSION) #define PEAKCAN_PROPERTY_CHANNEL_VERSION (CANPROP_GET_VENDOR_PROP + PCAN_CHANNEL_VERSION) #define PEAKCAN_PROPERTY_HARDWARE_NAME (CANPROP_GET_VENDOR_PROP + PCAN_HARDWARE_NAME) diff --git a/Sources/PeakCAN_Defines.h b/Sources/PeakCAN_Defines.h index 883eb93..5a4965b 100644 --- a/Sources/PeakCAN_Defines.h +++ b/Sources/PeakCAN_Defines.h @@ -152,6 +152,7 @@ extern "C" { #define PCAN_CHANNEL_VERSION 0x06U //!< PCAN device channel version parameter #define PCAN_HARDWARE_NAME 0x0EU //!< PCAN hardware name parameter #define PCAN_CONTROLLER_NUMBER 0x10U //!< CAN-Controller number of a PCAN-Channel +#define PCAN_DEVICE_GUID 0x30U //!< Global unique device identifier (GUID) //#define PCAN_SERIAL_NUMBER 0x??U //#define PCAN_CLOCK_DOMAINS 0x??U // TODO: define more or all parameters diff --git a/Trial/Sources/main.cpp b/Trial/Sources/main.cpp index 3099975..c875a04 100644 --- a/Trial/Sources/main.cpp +++ b/Trial/Sources/main.cpp @@ -266,37 +266,37 @@ int main(int argc, const char * argv[]) { } /* information from library */ if (option_info) { - retVal = myDriver.GetProperty(CANPROP_GET_SPEC, (void *)&u16Val, sizeof(uint16_t)); + retVal = myDriver.GetProperty(CANPROP_GET_SPEC, (void*)&u16Val, sizeof(uint16_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_SPEC): value = %u.%u\n", (uint8_t)(u16Val >> 8), (uint8_t)u16Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_SPEC) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_VERSION, (void *)&u16Val, sizeof(uint16_t)); + retVal = myDriver.GetProperty(CANPROP_GET_VERSION, (void*)&u16Val, sizeof(uint16_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_VERSION): value = %u.%u\n", (uint8_t)(u16Val >> 8), (uint8_t)u16Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_VERSION) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_PATCH_NO, (void *)&u8Val, sizeof(uint8_t)); + retVal = myDriver.GetProperty(CANPROP_GET_PATCH_NO, (void*)&u8Val, sizeof(uint8_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_PATCH_NO): value = %u\n", u8Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_PATCH_NO) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_BUILD_NO, (void *)&u32Val, sizeof(uint32_t)); + retVal = myDriver.GetProperty(CANPROP_GET_BUILD_NO, (void*)&u32Val, sizeof(uint32_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_BUILD_NO): value = %07" PRIx32 "\n", u32Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_BUILD_NO) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_LIBRARY_ID, (void *)&i32Val, sizeof(int32_t)); + retVal = myDriver.GetProperty(CANPROP_GET_LIBRARY_ID, (void*)&i32Val, sizeof(int32_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_LIBRARY_ID): value = %d\n", i32Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_LIBRARY_ID) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_LIBRARY_DLLNAME, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(CANPROP_GET_LIBRARY_DLLNAME, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_LIBRARY_DLLNAME): value = '%s'\n", szVal); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_LIBRARY_DLLNAME) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_LIBRARY_VENDOR, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(CANPROP_GET_LIBRARY_VENDOR, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_LIBRARY_VENDOR): value = '%s'\n", szVal); else @@ -316,30 +316,30 @@ int main(int argc, const char * argv[]) { n++; } #else - retVal = myDriver.SetProperty(CANPROP_SET_FIRST_CHANNEL, (void *)NULL, 0U); + retVal = myDriver.SetProperty(CANPROP_SET_FIRST_CHANNEL, (void*)NULL, 0U); while (retVal == CCanApi::NoError) { fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_SET_%s_CHANNEL): OK\n", !n ? "FIRST" : "NEXT"); - retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_NO, (void *)&i32Val, sizeof(int32_t)); + retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_NO, (void*)&i32Val, sizeof(int32_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_CHANNEL_NO): value = %d\n", i32Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_CHANNEL_NO) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_NAME, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_NAME, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_CHANNEL_NAME): value = '%s'\n", szVal); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_CHANNEL_NAME) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_DLLNAME, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_DLLNAME, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_CHANNEL_DLLNAME): value = '%s'\n", szVal); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_CHANNEL_DLLNAME) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_VENDOR_ID, (void *)&i32Val, sizeof(int32_t)); + retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_VENDOR_ID, (void*)&i32Val, sizeof(int32_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_CHANNEL_VENDOR_ID): value = %d\n", i32Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_CHANNEL_VENDOR_ID) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_VENDOR_NAME, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_VENDOR_NAME, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_CHANNEL_VENDOR_NAME): value = '%s'\n", szVal); else @@ -365,9 +365,9 @@ int main(int argc, const char * argv[]) { result = CCanDriver::GetNextChannel(info); } #else - retVal = myDriver.SetProperty(CANPROP_SET_FIRST_CHANNEL, (void *)NULL, 0U); + retVal = myDriver.SetProperty(CANPROP_SET_FIRST_CHANNEL, (void*)NULL, 0U); while (retVal == CCanApi::NoError) { - retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_NO, (void *)&i32Val, sizeof(int32_t)); + retVal = myDriver.GetProperty(CANPROP_GET_CHANNEL_NO, (void*)&i32Val, sizeof(int32_t)); if (retVal == CCanApi::NoError) { retVal = CCanDriver::ProbeChannel(i32Val, opMode, state); fprintf(stdout, ">>> CCanApi::ProbeChannel(%i): state = %s", i32Val, @@ -376,7 +376,7 @@ int main(int argc, const char * argv[]) { (state == CCanApi::ChannelNotAvailable) ? "not available" : "not testable"); fprintf(stdout, "%s", (retVal == CCanApi::IllegalParameter) ? " (warning: Op.-Mode not supported)\n" : "\n"); } - retVal = myDriver.SetProperty(CANPROP_SET_NEXT_CHANNEL, (void *)NULL, 0U); + retVal = myDriver.SetProperty(CANPROP_SET_NEXT_CHANNEL, (void*)NULL, 0U); } #endif if (option_exit) @@ -412,61 +412,66 @@ int main(int argc, const char * argv[]) { fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_CAN_CHANNEL): value = %u\n", u8Val); //else [optional property] // fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_CAN_CHANNEL) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_DEVICE_TYPE, (void *)&i32Val, sizeof(int32_t)); + retVal = myDriver.GetProperty(CANPROP_GET_DEVICE_TYPE, (void*)&i32Val, sizeof(int32_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_DEVICE_TYPE): value = %d\n", i32Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_DEVICE_TYPE) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_DEVICE_NAME, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(CANPROP_GET_DEVICE_NAME, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_DEVICE_NAME): value = '%s'\n", szVal); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_DEVICE_NAME) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_DEVICE_VENDOR, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(CANPROP_GET_DEVICE_VENDOR, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_DEVICE_VENDOR): value = '%s'\n", szVal); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_DEVICE_VENDOR) returned %i\n", retVal); - retVal = myDriver.GetProperty(CANPROP_GET_DEVICE_DLLNAME, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(CANPROP_GET_DEVICE_DLLNAME, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_DEVICE_DLLNAME): value = '%s'\n", szVal); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_DEVICE_DLLNAME) returned %i\n", retVal); /* vendor-specific properties */ - retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_DEVICE_ID, (void *)&u32Val, sizeof(uint32_t)); + retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_DEVICE_ID, (void*)&u32Val, sizeof(uint32_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(PEAKCAN_PROPERTY_DEVICE_ID): value = 0x%x\n", u32Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(PEAKCAN_PROPERTY_DEVICE_ID) returned %i\n", retVal); - retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_API_VERSION, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_API_VERSION, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(PEAKCAN_PROPERTY_API_VERSION): value = '%s'\n", szVal); else fprintf(stderr, "+++ error: myDriver.GetProperty(PEAKCAN_PROPERTY_API_VERSION) returned %i\n", retVal); - retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_CHANNEL_VERSION, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_CHANNEL_VERSION, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(PEAKCAN_PROPERTY_CHANNEL_VERSION): value = '%s'\n", szVal); else fprintf(stderr, "+++ error: myDriver.GetProperty(PEAKCAN_PROPERTY_CHANNEL_VERSION) returned %i\n", retVal); - retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_HARDWARE_NAME, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_HARDWARE_NAME, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(PEAKCAN_PROPERTY_HARDWARE_NAME): value = '%s'\n", szVal); else fprintf(stderr, "+++ error: myDriver.GetProperty(PEAKCAN_PROPERTY_HARDWARE_NAME) returned %i\n", retVal); + retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_DEVICE_GUID, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); + if (retVal == CCanApi::NoError) + fprintf(stdout, ">>> myDriver.GetProperty(PEAKCAN_PROPERTY_DEVICE_GUID): value = '%s'\n", szVal); + //else [optional property] + // fprintf(stderr, "+++ error: myDriver.GetProperty(PEAKCAN_PROPERTY_DEVICE_GUID) returned %i\n", retVal); #if (0) - retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_SERIAL_NUMBER, (void *)szVal, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_SERIAL_NUMBER, (void*)szVal, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(PEAKCAN_PROPERTY_SERIAL_NUMBER): value = '%s'\n", szVal); else fprintf(stderr, "+++ error: myDriver.GetProperty(PEAKCAN_PROPERTY_SERIAL_NUMBER) returned %i\n", retVal); #endif - retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_CONTROLLER_NUMBER, (void *)&u32Val, sizeof(uint32_t)); + retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_CONTROLLER_NUMBER, (void*)&u32Val, sizeof(uint32_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(PEAKCAN_PROPERTY_CONTROLLER_NUMBER): value = %u\n", u32Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(PEAKCAN_PROPERTY_CONTROLLER_NUMBER) returned %i\n", retVal); #if (0) - retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_CAN_CLOCK_DOMAINS, (void *)clocks, CANPROP_MAX_BUFFER_SIZE); + retVal = myDriver.GetProperty(PEAKCAN_PROPERTY_CAN_CLOCK_DOMAINS, (void*)clocks, CANPROP_MAX_BUFFER_SIZE); if (retVal == CCanApi::NoError) { fprintf(stdout, ">>> myDriver.GetProperty(PEAKCAN_PROPERTY_CAN_CLOCK_DOMAINS): array ="); for (int i = 0; (clocks[i] != EOF) && (i < (int)(CANPROP_MAX_BUFFER_SIZE/sizeof(int32_t))); i++) @@ -476,18 +481,18 @@ int main(int argc, const char * argv[]) { //else [optional property] // fprintf(stderr, "+++ error: myDriver.GetProperty(PEAKCAN_PROPERTY_CAN_CLOCK_DOMAINS) returned %i\n", retVal); #endif - retVal = myDriver.GetProperty(CANPROP_GET_CAN_CLOCK, (void *)&i32Val, sizeof(int32_t)); + retVal = myDriver.GetProperty(CANPROP_GET_CAN_CLOCK, (void*)&i32Val, sizeof(int32_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_CAN_CLOCK): value = %d\n", i32Val); //else [optional property] // fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_CAN_CLOCK) returned %i\n", retVal); /* device capabilities */ - retVal = myDriver.GetProperty(CANPROP_GET_OP_CAPABILITY, (void *)&u8Val, sizeof(uint8_t)); + retVal = myDriver.GetProperty(CANPROP_GET_OP_CAPABILITY, (void*)&u8Val, sizeof(uint8_t)); if (retVal == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_OP_CAPABILITY): value = 0x%02X\n", u8Val); else fprintf(stderr, "+++ error: myDriver.GetProperty(CANPROP_GET_OP_CAPABILITY) returned %i\n", retVal); - if (myDriver.GetProperty(CANPROP_GET_OP_MODE, (void *)&u8Val, sizeof(uint8_t)) == CCanApi::NoError) + if (myDriver.GetProperty(CANPROP_GET_OP_MODE, (void*)&u8Val, sizeof(uint8_t)) == CCanApi::NoError) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_OP_MODE): value = 0x%02X\n", u8Val); } /* acceptance filtering */ @@ -719,16 +724,16 @@ int main(int argc, const char * argv[]) { /* some statistics */ if (option_stat || option_info) { uint64_t u64TxCnt, u64RxCnt, u64ErrCnt; - if ((myDriver.GetProperty(CANPROP_GET_TX_COUNTER, (void *)&u64TxCnt, sizeof(uint64_t)) == CCanApi::NoError) && - (myDriver.GetProperty(CANPROP_GET_RX_COUNTER, (void *)&u64RxCnt, sizeof(uint64_t)) == CCanApi::NoError) && - (myDriver.GetProperty(CANPROP_GET_ERR_COUNTER, (void *)&u64ErrCnt, sizeof(uint64_t)) == CCanApi::NoError)) + if ((myDriver.GetProperty(CANPROP_GET_TX_COUNTER, (void*)&u64TxCnt, sizeof(uint64_t)) == CCanApi::NoError) && + (myDriver.GetProperty(CANPROP_GET_RX_COUNTER, (void*)&u64RxCnt, sizeof(uint64_t)) == CCanApi::NoError) && + (myDriver.GetProperty(CANPROP_GET_ERR_COUNTER, (void*)&u64ErrCnt, sizeof(uint64_t)) == CCanApi::NoError)) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_*_COUNTER): TX = %" PRIu64 " RX = %" PRIu64 " ERR = %" PRIu64 "\n", u64TxCnt, u64RxCnt, u64ErrCnt); } if (option_stat) { uint32_t u32QueSize, u32QueHigh; uint64_t u64QueOvfl; - if ((myDriver.GetProperty(CANPROP_GET_RCV_QUEUE_SIZE, (void *)&u32QueSize, sizeof(uint32_t)) == CCanApi::NoError) && - (myDriver.GetProperty(CANPROP_GET_RCV_QUEUE_HIGH, (void *)&u32QueHigh, sizeof(uint32_t)) == CCanApi::NoError) && - (myDriver.GetProperty(CANPROP_GET_RCV_QUEUE_OVFL, (void *)&u64QueOvfl, sizeof(uint64_t)) == CCanApi::NoError)) + if ((myDriver.GetProperty(CANPROP_GET_RCV_QUEUE_SIZE, (void*)&u32QueSize, sizeof(uint32_t)) == CCanApi::NoError) && + (myDriver.GetProperty(CANPROP_GET_RCV_QUEUE_HIGH, (void*)&u32QueHigh, sizeof(uint32_t)) == CCanApi::NoError) && + (myDriver.GetProperty(CANPROP_GET_RCV_QUEUE_OVFL, (void*)&u64QueOvfl, sizeof(uint64_t)) == CCanApi::NoError)) fprintf(stdout, ">>> myDriver.GetProperty(CANPROP_GET_QUEUE_*): SIZE = %" PRIu32 " HIGH = %" PRIu32 " OVFL = %" PRIu64 "\n", u32QueSize, u32QueHigh, u64QueOvfl); } /* version information */ diff --git a/Utilities/can_moni/Driver.h b/Utilities/can_moni/Driver.h index 889c831..08d128b 100644 --- a/Utilities/can_moni/Driver.h +++ b/Utilities/can_moni/Driver.h @@ -25,12 +25,22 @@ #if (OPTION_CAN_2_0_ONLY != 0) #error Compilation with legacy CAN 2.0 frame format! #else -#define CAN_FD_SUPPORTED 1 // don't touch that dial -#define CAN_TRACE_SUPPORTED 0 // write trace file (1=PCAN) +#define CAN_FD_SUPPORTED 1 // don't touch that dial +#define CAN_TRACE_SUPPORTED 0 // write trace file (1=PCAN) #endif +#if !defined(__APPLE__) #define MONITOR_INTERFACE "PEAK-System PCAN Interfaces" +#else +#define MONITOR_INTERFACE "PEAK-System PCAN USB Interfaces" +#endif #define MONITOR_COPYRIGHT "2007,2012-2025 by Uwe Vogt, UV Software, Berlin" +#if defined(_WIN32) || defined(_WIN64) #define MONITOR_PLATFORM "Windows" +#elif defined(__linux__) +#define MONITOR_PLATFORM "Linux" +#elif defined(__APPLE__) +#define MONITOR_PLATFORM "Darwin" +#endif #define MONITOR_ALIASNAME "PCB:" #if (OPTION_PCAN_BIT_TIMING == 1) diff --git a/Utilities/can_moni/README.md b/Utilities/can_moni/README.md index 56e8c25..4969169 100644 --- a/Utilities/can_moni/README.md +++ b/Utilities/can_moni/README.md @@ -14,8 +14,7 @@ Options: /MASK: acceptance mask for 11-bit IDs (default=0x000) /XTD-CODE: acceptance code for 29-bit IDs (default=0x00000000) /XTD-MASK: acceptance mask for 29-bit IDs (default=0x00000000) - /Mode:(2.0|FDf[+BRS]) CAN operation mode: CAN 2.0 or CAN FD mode - /SHARED shared CAN controller access (if supported) + /Mode:(CCf|FDf[+BRS]) CAN operation mode: CAN CC or CAN FD mode /MONitor:(No|Yes) | /LISTEN-ONLY monitor mode (listen-only mode) /ERR:(No|Yes) | /ERROR-FRAMES allow reception of error frames /RTR:(Yes|No) allow remote frames (RTR frames) @@ -23,14 +22,14 @@ Options: /BauDrate: CAN bit-timing in kbps (default=250), or /BitRate: CAN bit-rate settings (as key/value list) /Verbose show detailed bit-rate settings - /LIST-BITRATES[:(2.0|FDf[+BRS])] list standard bit-rate settings and exit + /LIST-BITRATES[:(CCf|FDf[+BRS])] list standard bit-rate settings and exit /LIST-BOARDS | /LIST list all supported CAN interfaces and exit /TEST-BOARDS | /TEST list all available CAN interfaces and exit /JSON-file: write configuration into JSON file and exit /HELP | /? display this help screen and exit /VERSION show version information and exit Arguments: - CAN identifier (11-bit) + CAN identifier (11-bit or 29-bit) CAN interface board (list all with /LIST) CAN baud rate index (default=3): 0 = 1000 kbps @@ -53,7 +52,7 @@ Arguments: data_brp= bit-rate prescaler (FD data) data_tseg1= time segment 1 (FD data) data_tseg2= time segment 2 (FD data) - data_sjw= sync. jump width (FD data). + data_sjw= sync. jump width (FD data) Hazard note: If you connect your CAN device to a real CAN network when using this program, you might damage your application. diff --git a/Utilities/can_moni/Sources/.gitignore b/Utilities/can_moni/Sources/.gitignore index ce4476c..90ec22b 100644 --- a/Utilities/can_moni/Sources/.gitignore +++ b/Utilities/can_moni/Sources/.gitignore @@ -1,5 +1 @@ .svn -# Not realized yet -ipc_server.* -# Not using IPC client -ipc_client.* diff --git a/Utilities/can_moni/Sources/Message.cpp b/Utilities/can_moni/Sources/Message.cpp index b4117ff..87f948f 100644 --- a/Utilities/can_moni/Sources/Message.cpp +++ b/Utilities/can_moni/Sources/Message.cpp @@ -56,7 +56,7 @@ // Methods to format a CAN message // bool CCanMessage::Format(TCanMessage message, uint64_t counter, char *string, size_t length) { - char *szMessage = msg_format_message(&message, MSG_RX_MESSAGE, counter, 0); + char *szMessage = msg_format_message((const msg_message_t*)&message, MSG_RX_MESSAGE, counter, 0); if (szMessage) { strncpy(string, szMessage, length); return true; @@ -87,3 +87,7 @@ bool CCanMessage::SetAsciiFormat(EFormatOption option) { bool CCanMessage::SetWraparound(EFormatWraparound option) { return msg_set_fmt_wraparound((msg_fmt_wraparound_t) option) ? true : false; } + +bool CCanMessage::Parse(const char *string, TCanMessage &message, uint32_t &count, uint64_t &cycle, int &increment) { + return msg_parse(string, (msg_message_t*)&message, &count, &cycle, &increment) == 0 ? true : false; +} diff --git a/Utilities/can_moni/Sources/Message.h b/Utilities/can_moni/Sources/Message.h index 2a1789f..53f3d2f 100644 --- a/Utilities/can_moni/Sources/Message.h +++ b/Utilities/can_moni/Sources/Message.h @@ -86,6 +86,7 @@ class CCanMessage { static bool SetAsciiFormat(EFormatOption option); static bool SetWraparound(EFormatWraparound option); static bool Format(TCanMessage message, uint64_t counter, char *string, size_t length); + static bool Parse(const char *string, TCanMessage &message, uint32_t &count, uint64_t &cycle, int &increment); }; /// \} diff --git a/Utilities/can_moni/Sources/Options.cpp b/Utilities/can_moni/Sources/Options.cpp index 77bcd8e..4f9b9d7 100644 --- a/Utilities/can_moni/Sources/Options.cpp +++ b/Utilities/can_moni/Sources/Options.cpp @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: GPL-2.0-or-later // // CAN Monitor for generic Interfaces (CAN API V3) // @@ -18,7 +18,7 @@ // with this program; if not, see . // #if defined(_WIN32) || defined(_WIN64) -// for Windows OS (x86 and x64) +// for Windows OS (x86 and x64) #include "Options_w.cpp" #else // for POSIX OS (Linux, Darwin) diff --git a/Utilities/can_moni/Sources/Options.h b/Utilities/can_moni/Sources/Options.h index 2ebccc8..1161c8f 100644 --- a/Utilities/can_moni/Sources/Options.h +++ b/Utilities/can_moni/Sources/Options.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: GPL-2.0-or-later // // CAN Monitor for generic Interfaces (CAN API V3) // @@ -31,11 +31,11 @@ #if !defined(_WIN32) && !defined(_WIN64) #define CAN_MONI_WARRANTY "This program comes with ABSOLUTELY NO WARRANTY!\n\n" \ "This is free software, and you are welcome to redistribute it\n" \ - "under certain conditions; type `--version' for details."; + "under certain conditions; type `" CAN_MONI_PROGRAM " --version' for details."; #else #define CAN_MONI_WARRANTY "This program comes with ABSOLUTELY NO WARRANTY!\n\n" \ "This is free software, and you are welcome to redistribute it\n" \ - "under certain conditions; type '/VERSION' for details."; + "under certain conditions; type '" CAN_MONI_PROGRAM " /VERSION' for details."; #endif #define CAN_MONI_LICENSE "This program is free software; you can redistribute it and/or modify\n" \ "it under the terms of the GNU General Public License as published by\n" \ @@ -72,7 +72,7 @@ struct SOptions { } m_StdFilter, m_XtdFilter; char* m_szExcludeList; #if (CAN_TRACE_SUPPORTED != 0) - enum { + enum ETraceMode { eTraceOff, eTraceBinary, eTraceLogger, diff --git a/Utilities/can_moni/Sources/Options_p.cpp b/Utilities/can_moni/Sources/Options_p.cpp index 5b0474c..c0c0933 100644 --- a/Utilities/can_moni/Sources/Options_p.cpp +++ b/Utilities/can_moni/Sources/Options_p.cpp @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: GPL-2.0-or-later // // CAN Monitor for generic Interfaces (CAN API V3) // @@ -97,7 +97,9 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) int optBitrate = 0; int optVerbose = 0; int optMode = 0; +#if (CAN_SHARED_SUPPORTED != 0) int optShared = 0; +#endif int optListenOnly = 0; int optErrorFrames = 0; int optExtendedFrames = 0; @@ -143,10 +145,18 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) // command-line options int show_version = 0; struct option long_options[] = { + {"time", required_argument, 0, 't'}, + {"id", required_argument, 0, 'i'}, + {"data", required_argument, 0, 'd'}, + {"ascii", required_argument, 0, 'a'}, + {"wrap", required_argument, 0, 'w'}, + {"wraparound", required_argument, 0, 'w'}, + {"exclude", required_argument, 0, 'x'}, + {"script", required_argument, 0, 's'}, {"baudrate", required_argument, 0, 'b'}, {"bitrate", required_argument, 0, 'B'}, {"verbose", no_argument, 0, 'v'}, - {"protocol", required_argument, 0, 'z'}, + {"protocol", required_argument, 0, 'Z'}, {"mode", required_argument, 0, 'm'}, {"shared", no_argument, 0, 'S'}, {"listen-only", no_argument, 0, 'M'}, @@ -157,15 +167,7 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) {"mask", required_argument, 0, '2'}, {"xtd-code", required_argument, 0, '3'}, {"xtd-mask", required_argument, 0, '4'}, - {"time", required_argument, 0, 't'}, - {"id", required_argument, 0, 'i'}, - {"data", required_argument, 0, 'd'}, - {"ascii", required_argument, 0, 'a'}, - {"wrap", required_argument, 0, 'w'}, - {"wraparound", required_argument, 0, 'w'}, - {"exclude", required_argument, 0, 'x'}, - {"script", required_argument, 0, 's'}, - {"trace", required_argument, 0, 'y'}, + {"trace", required_argument, 0, 'Y'}, {"list-bitrates", optional_argument, 0, 'l'}, #if (OPTION_CANAPI_LIBRARY != 0) {"list-boards", optional_argument, 0, 'L'}, @@ -191,9 +193,9 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) #endif // (2) scan command-line for options #if (OPTION_CANAPI_LIBRARY != 0) - while ((opt = getopt_long(argc, (char * const *)argv, "b:vp:z:m:t:i:d:a:w:x:s:y:lLTh", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, (char * const *)argv, "b:vm:t:i:d:a:w:x:s:lLTp:h", long_options, NULL)) != -1) { #else - while ((opt = getopt_long(argc, (char * const *)argv, "b:vz:m:t:i:d:a:w:x:s:y:lLTj:h", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, (char * const *)argv, "b:vm:t:i:d:a:w:x:s:lLTj:h", long_options, NULL)) != -1) { #endif switch (opt) { /* option '--baudrate=' (-b) */ @@ -279,7 +281,7 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) #endif #if (SERIAL_CAN_SUPPORTED != 0) /* option '--protocol=(Lawicel|CANable)' */ - case 'z': + case 'Z': if (optProtocol++) { fprintf(err, "%s: duplicated option `--protocol' (%c)\n", m_szBasename, opt); return 1; @@ -309,7 +311,8 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) return 1; } if (!strcasecmp(optarg, "DEFAULT") || !strcasecmp(optarg, "CLASSIC") || !strcasecmp(optarg, "CLASSICAL") || - !strcasecmp(optarg, "CAN20") || !strcasecmp(optarg, "CAN2.0") || !strcasecmp(optarg, "2.0")) + !strcasecmp(optarg, "CAN20") || !strcasecmp(optarg, "CAN2.0") || !strcasecmp(optarg, "2.0") || + !strcasecmp(optarg, "CANCC") || !strcasecmp(optarg, "CC") || !strcasecmp(optarg, "CCF")) m_OpMode.byte |= CANMODE_DEFAULT; #if (CAN_FD_SUPPORTED != 0) else if (!strcasecmp(optarg, "CANFD") || !strcasecmp(optarg, "FD") || !strcasecmp(optarg, "FDF")) @@ -322,6 +325,7 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) return 1; } break; +#if (CAN_SHARED_SUPPORTED != 0) /* option '--shared' */ case 'S': if (optShared++) { @@ -334,6 +338,7 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) } m_OpMode.byte |= CANMODE_SHRD; break; +#endif /* option '--listen-only' */ case 'M': if (optListenOnly++) { @@ -462,9 +467,9 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) } m_XtdFilter.m_u32Mask = (uint32_t)intarg; break; - /* option '--trace=(ON|OFF)' (-y) */ + /* option '--trace=(ON|OFF)' */ #if (CAN_TRACE_SUPPORTED != 0) - case 'y': + case 'Y': if (optTraceMode++) { fprintf(err, "%s: duplicated option `--trace'\n", m_szBasename); return 1; @@ -647,7 +652,8 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) return 1; } if (!strcasecmp(optarg, "DEFAULT") || !strcasecmp(optarg, "CLASSIC") || !strcasecmp(optarg, "CLASSICAL") || - !strcasecmp(optarg, "CAN20") || !strcasecmp(optarg, "CAN2.0") || !strcasecmp(optarg, "2.0")) + !strcasecmp(optarg, "CAN20") || !strcasecmp(optarg, "CAN2.0") || !strcasecmp(optarg, "2.0") || + !strcasecmp(optarg, "CANCC") || !strcasecmp(optarg, "CC") || !strcasecmp(optarg, "CCF")) m_OpMode.byte |= CANMODE_DEFAULT; #if (CAN_FD_SUPPORTED != 0) else if (!strcasecmp(optarg, "CANFD") || !strcasecmp(optarg, "FD") || !strcasecmp(optarg, "FDF")) @@ -811,11 +817,13 @@ void SOptions::ShowUsage(FILE* stream, bool args) { fprintf(stream, " -p, --path= search path for JSON configuration files\n"); #endif #if (CAN_FD_SUPPORTED != 0) - fprintf(stream, " -m, --mode=(2.0|FDF[+BRS]) CAN operation mode: CAN 2.0 or CAN FD mode\n"); + fprintf(stream, " -m, --mode=(CCF|FDF[+BRS]) CAN operation mode: CAN CC or CAN FD mode\n"); #else - fprintf(stream, " -m, --mode=2.0 CAN operation mode: CAN 2.0\n"); + fprintf(stream, " -m, --mode=CCF CAN operation mode: CAN CC mode\n"); #endif +#if (CAN_SHARED_SUPPORTED != 0) fprintf(stream, " --shared shared CAN controller access (if supported)\n"); +#endif fprintf(stream, " --listen-only monitor mode (listen-only mode)\n"); fprintf(stream, " --error-frames allow reception of error frames\n"); fprintf(stream, " --no-remote-frames suppress remote frames (RTR frames)\n"); @@ -824,10 +832,14 @@ void SOptions::ShowUsage(FILE* stream, bool args) { fprintf(stream, " --bitrate= CAN bit-rate settings (as key/value list)\n"); fprintf(stream, " -v, --verbose show detailed bit-rate settings\n"); #if (CAN_TRACE_SUPPORTED != 0) - fprintf(stream, " -y, --trace=(ON|OFF) write a trace file (default=OFF)\n"); +#if (CAN_TRACE_SUPPORTED == 1) + fprintf(stream, " --trace=(ON|OFF) write a trace file (default=OFF)\n"); +#else + fprintf(stream, " --trace=(BIN|CSV|TRC) write a trace file (default=OFF)\n"); +#endif #endif #if (SERIAL_CAN_SUPPORTED != 0) - fprintf(stream, " -z, --protocol=(Lawicel|CANable) select SLCAN protocol (default=Lawicel)\n"); + fprintf(stream, " --protocol=(Lawicel|CANable) select SLCAN protocol (default=Lawicel)\n"); #endif #if (CAN_FD_SUPPORTED != 0) fprintf(stream, " --list-bitrates[=] list standard bit-rate settings and exit\n"); @@ -846,7 +858,7 @@ void SOptions::ShowUsage(FILE* stream, bool args) { fprintf(stream, " --version show version information and exit\n"); if (args) { fprintf(stream, "Arguments:\n"); - fprintf(stream, " CAN identifier (11-bit)\n"); + fprintf(stream, " CAN identifier (11-bit or 29-bit)\n"); fprintf(stream, " CAN interface board (list all with /LIST)\n"); fprintf(stream, " CAN baud rate index (default=3):\n"); fprintf(stream, " 0 = 1000 kbps\n"); diff --git a/Utilities/can_moni/Sources/Options_w.cpp b/Utilities/can_moni/Sources/Options_w.cpp index ae53284..55834af 100644 --- a/Utilities/can_moni/Sources/Options_w.cpp +++ b/Utilities/can_moni/Sources/Options_w.cpp @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: GPL-2.0-or-later // // CAN Monitor for generic Interfaces (CAN API V3) // @@ -186,7 +186,9 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) int optBitrate = 0; int optVerbose = 0; int optMode = 0; +#if (CAN_SHARED_SUPPORTED != 0) int optShared = 0; +#endif int optListenOnly = 0; int optErrorFrames = 0; int optExtendedFrames = 0; @@ -360,7 +362,8 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) return 1; } if (!strcasecmp(optarg, "DEFAULT") || !strcasecmp(optarg, "CLASSIC") || !strcasecmp(optarg, "CLASSICAL") || - !strcasecmp(optarg, "CAN20") || !strcasecmp(optarg, "CAN2.0") || !strcasecmp(optarg, "2.0")) + !strcasecmp(optarg, "CAN20") || !strcasecmp(optarg, "CAN2.0") || !strcasecmp(optarg, "2.0") || + !strcasecmp(optarg, "CANCC") || !strcasecmp(optarg, "CC") || !strcasecmp(optarg, "CCF")) m_OpMode.byte |= CANMODE_DEFAULT; #if (CAN_FD_SUPPORTED != 0) else if (!strcasecmp(optarg, "CANFD") || !strcasecmp(optarg, "FD") || !strcasecmp(optarg, "FDF")) @@ -373,6 +376,7 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) return 1; } break; +#if (CAN_SHARED_SUPPORTED != 0) /* option '--shared' */ case OP_SHARED_STR: case OP_SHARED_CHR: @@ -386,6 +390,7 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) } m_OpMode.byte |= CANMODE_SHRD; break; +#endif /* option '--listen-only' */ case OP_MON_STR: case OP_MONITOR_STR: @@ -565,7 +570,7 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) } m_XtdFilter.m_u32Mask = (uint32_t)intarg; break; - /* option '--trace=(ON|OFF)' (-y) */ + /* option '--trace=(ON|OFF)' */ #if (CAN_TRACE_SUPPORTED != 0) case TRACEFILE_STR: case TRACEFILE_CHR: @@ -757,7 +762,8 @@ int SOptions::ScanCommanline(int argc, const char* argv[], FILE* err, FILE* out) return 1; } if (!strcasecmp(optarg, "DEFAULT") || !strcasecmp(optarg, "CLASSIC") || !strcasecmp(optarg, "CLASSICAL") || - !strcasecmp(optarg, "CAN20") || !strcasecmp(optarg, "CAN2.0") || !strcasecmp(optarg, "2.0")) + !strcasecmp(optarg, "CAN20") || !strcasecmp(optarg, "CAN2.0") || !strcasecmp(optarg, "2.0") || + !strcasecmp(optarg, "CANCC") || !strcasecmp(optarg, "CC") || !strcasecmp(optarg, "CCF")) m_OpMode.byte |= CANMODE_DEFAULT; #if (CAN_FD_SUPPORTED != 0) else if (!strcasecmp(optarg, "CANFD") || !strcasecmp(optarg, "FD") || !strcasecmp(optarg, "FDF")) @@ -909,11 +915,13 @@ void SOptions::ShowUsage(FILE* stream, bool args) { fprintf(stream, " /Path: search path for JSON configuration files\n"); #endif #if (CAN_FD_SUPPORTED != 0) - fprintf(stream, " /Mode:(2.0|FDf[+BRS]) CAN operation mode: CAN 2.0 or CAN FD mode\n"); + fprintf(stream, " /Mode:(CCf|FDf[+BRS]) CAN operation mode: CAN CC or CAN FD mode\n"); #else - fprintf(stream, " /Mode:2.0 CAN operation mode: CAN 2.0\n"); + fprintf(stream, " /Mode:CCf CAN operation mode: CAN CC mode\n"); #endif +#if (CAN_SHARED_SUPPORTED != 0) fprintf(stream, " /SHARED shared CAN controller access (if supported)\n"); +#endif fprintf(stream, " /MONitor:(No|Yes) | /LISTEN-ONLY monitor mode (listen-only mode)\n"); fprintf(stream, " /ERR:(No|Yes) | /ERROR-FRAMES allow reception of error frames\n"); fprintf(stream, " /RTR:(Yes|No) allow remote frames (RTR frames)\n"); @@ -921,14 +929,18 @@ void SOptions::ShowUsage(FILE* stream, bool args) { fprintf(stream, " /BauDrate: CAN bit-timing in kbps (default=250), or\n"); fprintf(stream, " /BitRate: CAN bit-rate settings (as key/value list)\n"); fprintf(stream, " /Verbose show detailed bit-rate settings\n"); -#if (SERIAL_CAN_SUPPORTED != 0) - fprintf(stream, " /PRotocol:(Lawicel|CANable) select SLCAN protocol (default=Lawicel)\n"); -#endif #if (CAN_TRACE_SUPPORTED != 0) +#if (CAN_TRACE_SUPPORTED == 1) fprintf(stream, " /TRaCe:(ON|OFF) write a trace file (default=OFF)\n"); +#else + fprintf(stream, " /TRaCe:(BIN|CSV|TRC) write a trace file (default=OFF)\n"); +#endif +#endif +#if (SERIAL_CAN_SUPPORTED != 0) + fprintf(stream, " /PRotocol:(Lawicel|CANable) select SLCAN protocol (default=Lawicel)\n"); #endif #if (CAN_FD_SUPPORTED != 0) - fprintf(stream, " /LIST-BITRATES[:(2.0|FDf[+BRS])] list standard bit-rate settings and exit\n"); + fprintf(stream, " /LIST-BITRATES[:(CCf|FDf[+BRS])] list standard bit-rate settings and exit\n"); #else fprintf(stream, " /LIST-BITRATES[:2.0] list standard bit-rate settings and exit\n"); #endif @@ -944,7 +956,7 @@ void SOptions::ShowUsage(FILE* stream, bool args) { fprintf(stream, " /VERSION show version information and exit\n"); if (args) { fprintf(stream, "Arguments:\n"); - fprintf(stream, " CAN identifier (11-bit)\n"); + fprintf(stream, " CAN identifier (11-bit or 29-bit)\n"); fprintf(stream, " CAN interface board (list all with /LIST)\n"); fprintf(stream, " CAN baud rate index (default=3):\n"); fprintf(stream, " 0 = 1000 kbps\n"); diff --git a/Utilities/can_moni/Sources/Timer.cpp b/Utilities/can_moni/Sources/Timer.cpp index 5a32538..f63775d 100644 --- a/Utilities/can_moni/Sources/Timer.cpp +++ b/Utilities/can_moni/Sources/Timer.cpp @@ -262,4 +262,44 @@ double CTimer::DiffTime(struct timespec start, struct timespec stop) { ((double)start.tv_sec + ((double)start.tv_nsec / 1000000000.f))); } -// $Id: Timer.cpp 841 2025-01-17 18:54:40Z quaoar $ Copyright (c) UV Software, Berlin // +static inline uint64_t abs_int64(int64_t x) { + return (x < 0) ? (uint64_t)(-x) : (uint64_t)x; +} + +uint64_t CTimer::DiffTimeInUsec(struct timespec start, struct timespec stop) { + int64_t sec_diff = (int64_t)(stop.tv_sec - start.tv_sec); + int64_t nsec_diff = (int64_t)(stop.tv_nsec - start.tv_nsec); + /* normalize time differences */ + if (nsec_diff < 0) { + sec_diff -= (int64_t)1; + nsec_diff += (int64_t)1000000000; + } + /* convert to microseconds (rounded up) */ + return abs_int64((sec_diff * (int64_t)1000000) + ((nsec_diff + (int64_t)500) / (int64_t)1000)); +} + +uint64_t CTimer::DiffTimeInMsec(struct timespec start, struct timespec stop) { + int64_t sec_diff = (int64_t)(stop.tv_sec - start.tv_sec); + int64_t nsec_diff = (int64_t)(stop.tv_nsec - start.tv_nsec); + /* normalize time differences */ + if (nsec_diff < 0) { + sec_diff -= (int64_t)1; + nsec_diff += (int64_t)1000000000; + } + // convert to milliseconds (rounded up) + return abs_int64((sec_diff * (int64_t)1000) + ((nsec_diff + (int64_t)500000) / (int64_t)1000000)); +} + +uint64_t CTimer::DiffTimeInSec(struct timespec start, struct timespec stop) { + int64_t sec_diff = (int64_t)(stop.tv_sec - start.tv_sec); + int64_t nsec_diff = (int64_t)(stop.tv_nsec - start.tv_nsec); + /* normalize time differences */ + if (nsec_diff < 0) { + sec_diff -= (int64_t)1; + nsec_diff += (int64_t)1000000000; + } + // convert to seconds (rounded up) + return abs_int64(sec_diff + ((nsec_diff + (int64_t)500000000) / (int64_t)1000000000)); +} + +// $Id: Timer.cpp 847 2025-02-22 12:50:44Z sedna $ Copyright (c) UV Software, Berlin // diff --git a/Utilities/can_moni/Sources/Timer.h b/Utilities/can_moni/Sources/Timer.h index dc6c1d1..ef48514 100644 --- a/Utilities/can_moni/Sources/Timer.h +++ b/Utilities/can_moni/Sources/Timer.h @@ -56,6 +56,7 @@ #include #include +#include #if defined(_WIN32) || defined(_WIN64) #include #endif @@ -88,8 +89,11 @@ class CTimer { static struct timespec GetTime(); // time with nanosecond resolution static double DiffTime(struct timespec start, struct timespec stop); + static uint64_t DiffTimeInUsec(struct timespec start, struct timespec stop); + static uint64_t DiffTimeInMsec(struct timespec start, struct timespec stop); + static uint64_t DiffTimeInSec(struct timespec start, struct timespec stop); }; #endif // TIMER_H_INCLUDED -// $Id: Timer.h 841 2025-01-17 18:54:40Z quaoar $ Copyright (c) UV Software, Berlin // +// $Id: Timer.h 847 2025-02-22 12:50:44Z sedna $ Copyright (c) UV Software, Berlin // diff --git a/Utilities/can_moni/Sources/main.cpp b/Utilities/can_moni/Sources/main.cpp index cc98d8b..e2b2cc2 100644 --- a/Utilities/can_moni/Sources/main.cpp +++ b/Utilities/can_moni/Sources/main.cpp @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: GPL-2.0-or-later // // CAN Monitor for generic Interfaces (CAN API V3) // @@ -171,7 +171,7 @@ int main(int argc, const char* argv[]) { /* - show operation mode, bit-rate settings and acceptance filter (if set) */ if (opts.m_fVerbose) { /* -- operation mode */ - fprintf(stdout, "Op.-mode=%s", (opts.m_OpMode.byte & CANMODE_FDOE) ? "CANFD" : "CAN2.0"); + fprintf(stdout, "Op.-mode=%s", (opts.m_OpMode.byte & CANMODE_FDOE) ? "CAN FD" : "CAN CC"); if ((opts.m_OpMode.byte & CANMODE_BRSE)) fprintf(stdout, "+BRS"); if ((opts.m_OpMode.byte & CANMODE_NISO)) fprintf(stdout, "+NISO"); if ((opts.m_OpMode.byte & CANMODE_SHRD)) fprintf(stdout, "+SHRD"); diff --git a/Utilities/can_send/COPYING b/Utilities/can_send/COPYING new file mode 100644 index 0000000..9efa6fb --- /dev/null +++ b/Utilities/can_send/COPYING @@ -0,0 +1,338 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Moe Ghoul, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/Utilities/can_send/Driver.h b/Utilities/can_send/Driver.h new file mode 100644 index 0000000..5a7a17d --- /dev/null +++ b/Utilities/can_send/Driver.h @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// +// CAN Sender for PEAK-System PCAN Interfaces (CAN API V3) +// +// Copyright (c) 2025 Uwe Vogt, UV Software, Berlin (info@uv-software.com) +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, see . +// +#ifndef DRIVER_H_INCLUDED +#define DRIVER_H_INCLUDED + +#include "PeakCAN.h" + +#if (OPTION_CAN_2_0_ONLY != 0) +#error Compilation with legacy CAN 2.0 frame format! +#else +#define CAN_FD_SUPPORTED 1 // don't touch that dial +#define CAN_TRACE_SUPPORTED 0 // write trace file (1=PCAN) +#endif +#if !defined(__APPLE__) +#define SENDER_INTERFACE "PEAK-System PCAN Interfaces" +#else +#define SENDER_INTERFACE "PEAK-System PCAN USB Interfaces" +#endif +#define SENDER_COPYRIGHT "2025 by Uwe Vogt, UV Software, Berlin" +#if defined(_WIN32) || defined(_WIN64) +#define SENDER_PLATFORM "Windows" +#elif defined(__linux__) +#define SENDER_PLATFORM "Linux" +#elif defined(__APPLE__) +#define SENDER_PLATFORM "Darwin" +#endif +#define SENDER_ALIASNAME "PCB:" + +#if (OPTION_PCAN_BIT_TIMING == 1) +#define BITRATE_1M(x) PEAKCAN_BR_1M(x) +#define BITRATE_800K(x) PEAKCAN_BR_800K(x) +#define BITRATE_500K(x) PEAKCAN_BR_500K(x) +#define BITRATE_250K(x) PEAKCAN_BR_250K(x) +#define BITRATE_125K(x) PEAKCAN_BR_125K(x) +#define BITRATE_100K(x) PEAKCAN_BR_100K(x) +#define BITRATE_50K(x) PEAKCAN_BR_50K(x) +#define BITRATE_20K(x) PEAKCAN_BR_20K(x) +#define BITRATE_10K(x) PEAKCAN_BR_10K(x) +#define BITRATE_5K(x) PEAKCAN_BR_5K(x) +#else +#define BITRATE_1M(x) DEFAULT_CAN_BR_1M(x) +#define BITRATE_800K(x) DEFAULT_CAN_BR_800K(x) +#define BITRATE_500K(x) DEFAULT_CAN_BR_500K(x) +#define BITRATE_250K(x) DEFAULT_CAN_BR_250K(x) +#define BITRATE_125K(x) DEFAULT_CAN_BR_125K(x) +#define BITRATE_100K(x) DEFAULT_CAN_BR_100K(x) +#define BITRATE_50K(x) DEFAULT_CAN_BR_50K(x) +#define BITRATE_20K(x) DEFAULT_CAN_BR_20K(x) +#define BITRATE_10K(x) DEFAULT_CAN_BR_10K(x) +#define BITRATE_5K(x) DEFAULT_CAN_BR_5K(x) +#endif +#if (CAN_FD_SUPPORTED != 0) +#if (OPTION_PCAN_BIT_TIMING == 1) +#define BITRATE_FD_1M(x) PEAKCAN_FD_BR_1M(x) +#define BITRATE_FD_500K(x) PEAKCAN_FD_BR_500K(x) +#define BITRATE_FD_250K(x) PEAKCAN_FD_BR_250K(x) +#define BITRATE_FD_125K(x) PEAKCAN_FD_BR_125K(x) +#define BITRATE_FD_1M8M(x) PEAKCAN_FD_BR_1M8M(x) +#define BITRATE_FD_500K4M(x) PEAKCAN_FD_BR_500K4M(x) +#define BITRATE_FD_250K2M(x) PEAKCAN_FD_BR_250K2M(x) +#define BITRATE_FD_125K1M(x) PEAKCAN_FD_BR_125K1M(x) +#else +#define BITRATE_FD_1M(x) DEFAULT_CAN_FD_BR_1M(x) +#define BITRATE_FD_500K(x) DEFAULT_CAN_FD_BR_500K(x) +#define BITRATE_FD_250K(x) DEFAULT_CAN_FD_BR_250K(x) +#define BITRATE_FD_125K(x) DEFAULT_CAN_FD_BR_125K(x) +#define BITRATE_FD_1M8M(x) DEFAULT_CAN_FD_BR_1M8M(x) +#define BITRATE_FD_500K4M(x) DEFAULT_CAN_FD_BR_500K4M(x) +#define BITRATE_FD_250K2M(x) DEFAULT_CAN_FD_BR_250K2M(x) +#define BITRATE_FD_125K1M(x) DEFAULT_CAN_FD_BR_125K1M(x) +#endif +#endif + +typedef CPeakCAN CCanDriver; + +#endif // DRIVER_H_INCLUDED diff --git a/Utilities/can_send/README.md b/Utilities/can_send/README.md new file mode 100644 index 0000000..bd54b8c --- /dev/null +++ b/Utilities/can_send/README.md @@ -0,0 +1,85 @@ +__CAN Sender for PEAK-System PCAN Interfaces, Version 0.4__ \ +Copyright © 2025 by Uwe Vogt, UV Software, Berlin + +``` +Usage: can_send [