Skip to content

Commit

Permalink
add option ISO_TP_USER_SEND_CAN_ARG (#36)
Browse files Browse the repository at this point in the history
* add option ISO_TP_USER_SEND_CAN_ARG which includes an additional void*
argument in isotp_user_send_can with which to pass adapter-specific
information.

* update CMakeLists.txt and README.md

* Added new contributor and PR to list

* Bumped up version

* Bumped up version

* Added new workflow which builds and tests the changes as defined in #36

* Added new workflow which builds and tests the changes as defined in #36

---------

Co-authored-by: Simon Cahill <[email protected]>
  • Loading branch information
driftregion and SimonCahill committed Aug 16, 2024
1 parent be9d46a commit 276549c
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 16 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/build-w-opt-can-arg.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: "CMake w/ changes from #36"

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release

jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Checkout Submodules
run: git submodule update --init --recursive

- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -Disotp_ENABLE_CAN_SEND_ARG=ON

- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}

10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ cmake_minimum_required(VERSION 3.10)
###
# Project definition
###
project(isotp LANGUAGES C VERSION 1.1.1 DESCRIPTION "A platform-agnostic ISOTP implementation in C for embedded devices.")
project(isotp LANGUAGES C VERSION 1.2.0 DESCRIPTION "A platform-agnostic ISOTP implementation in C for embedded devices.")

option(isotpc_USE_INCLUDE_DIR "Copy header files to separate include directory in current binary dir for better separation of header files to combat potential naming conflicts." OFF)
option(isotpc_STATIC_LIBRARY "Compile libisotpc as a static library, instead of a shared library." OFF)
option(isotpc_STATIC_LIBRARY_PIC "Make use of position independent code (PIC), when compiling as a static library (enabled automatically when building shared libraries)." OFF)
option(isotpc_PAD_CAN_FRAMES "Pad CAN frames to their full size." ON)
set(isotpc_CAN_FRAME_PAD_VALUE "0xAA" CACHE STRING "Padding byte value to be used in CAN frames if enabled")
option(isotpc_ENABLE_CAN_SEND_ARG "Adds an extra argument to isotp_user_send_can to better support multiple CAN interfaces." OFF)

if (isotpc_STATIC_LIBRARY)
add_library(isotp STATIC ${CMAKE_CURRENT_SOURCE_DIR}/isotp.c)
Expand Down Expand Up @@ -42,6 +43,13 @@ if (isotpc_PAD_CAN_FRAMES)
target_compile_definitions(isotp PRIVATE -DISO_TP_FRAME_PADDING -DISO_TP_FRAME_PADDING_VALUE=${isotpc_CAN_FRAME_PAD_VALUE})
endif()

###
# Include additional arg in isotp_user_send_can if required
###
if (isotpc_ENABLE_CAN_SEND_ARG)
target_compile_options(isotp PRIVATE -DISO_TP_USER_SEND_CAN_ARG)
endif()

###
# Check for debug builds
###
Expand Down
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
| [Phil Greenland](https://github.com/pgreenland) | Fixed PIC being generated for static binaries | #27 |
| [speedy-h](https://github.com/speedy-h) | Fixed compiler error when compiling with `-Wextra` caused by unused function params. | #32 |
| [kazetsukaimiko](https://github.com/kazetsukaimiko) | Added support for PlatformIO, a platform for distributing libraries for a variety of systems. | #35 |
| [driftregion](https://github.com/driftregion) | Added support for optional CAN arguments for adapter-specific information. | #36 |

Thank you everyone for contributing to this library and improving it!
Have you contributed and I've forgotten to mention you? Please let me know and I'll add you here!
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,46 @@ isotp-c supports this also, via options.

Either pass `-Disotpc_STATIC_LIBRARY=ON` via command-line or `set(isotpc_STATIC_LIBRARY ON CACHE BOOL "Enable static library for isotp-c")` in your CMakeLists.txt and the library will be built as a static library (`*.a|*.lib`) for your project to include.

#### Use of multiple CAN interfaces
For applications requiring multiple CAN interfaces, it is necessary to specify the interface in `isotp_user_send_can`.

In this case the config option `-DISO_TP_USER_SEND_CAN_ARG` may be enabled. The library may then be used as follows:

```c
// Objects representing two CAN interfaces: a and b.
CAN_IFACE_t can_a, can_b;

void init() {
// Two IsoTpLinks assumed to be bound to different CAN interfaces.
IsoTpLink link_a, link_b;

isotp_init_link(&link_a, ...);
isotp_init_link(&link_b, ...);

// After link initialization, the relevant CAN interface may be
// attached to the link.
link_a.user_send_can_arg = &can_a;
link_a.user_send_can_arg = &can_b;
}

int isotp_user_send_can(
const uint32_t arbitration_id,
const uint8_t *data,
const uint8_t size,
void *user_send_can_arg)
{
// It is then available for use inside isotp_user_send_can
int err = CAN_SEND((CAN_IFACE_t *)(user_send_can_arg), arbitration_id, data, size);
if (err) {
return ISOTP_RET_ERROR;
} else {
return ISOTP_RET_OK;
}
}

```
#### Inclusion in your CMake project
```cmake
###
Expand Down
46 changes: 34 additions & 12 deletions isotp.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ static int isotp_send_flow_control(const IsoTpLink* link, uint8_t flow_status, u

IsoTpCanMessage message;
int ret;
uint8_t size = 0;

/* setup message */
message.as.flow_control.type = ISOTP_PCI_TYPE_FLOW_CONTROL_FRAME;
Expand All @@ -43,20 +44,25 @@ static int isotp_send_flow_control(const IsoTpLink* link, uint8_t flow_status, u
/* send message */
#ifdef ISO_TP_FRAME_PADDING
(void) memset(message.as.flow_control.reserve, ISO_TP_FRAME_PADDING_VALUE, sizeof(message.as.flow_control.reserve));
ret = isotp_user_send_can(link->send_arbitration_id, message.as.data_array.ptr, sizeof(message));
size = sizeof(message);
#else
ret = isotp_user_send_can(link->send_arbitration_id,
message.as.data_array.ptr,
3);
size = 3;
#endif

ret = isotp_user_send_can(link->send_arbitration_id, message.as.data_array.ptr, size
#if defined (ISO_TP_USER_SEND_CAN_ARG)
,link->user_send_can_arg
#endif
);

return ret;
}

static int isotp_send_single_frame(const IsoTpLink* link, uint32_t id) {

IsoTpCanMessage message;
int ret;
uint8_t size = 0;

/* multi frame message length must greater than 7 */
assert(link->send_size <= 7);
Expand All @@ -69,13 +75,17 @@ static int isotp_send_single_frame(const IsoTpLink* link, uint32_t id) {
/* send message */
#ifdef ISO_TP_FRAME_PADDING
(void) memset(message.as.single_frame.data + link->send_size, ISO_TP_FRAME_PADDING_VALUE, sizeof(message.as.single_frame.data) - link->send_size);
ret = isotp_user_send_can(id, message.as.data_array.ptr, sizeof(message));
size = sizeof(message);
#else
ret = isotp_user_send_can(id,
message.as.data_array.ptr,
link->send_size + 1);
size = link->send_size + 1;
#endif

ret = isotp_user_send_can(link->send_arbitration_id, message.as.data_array.ptr, size
#if defined (ISO_TP_USER_SEND_CAN_ARG)
,link->user_send_can_arg
#endif
);

return ret;
}

Expand All @@ -94,7 +104,12 @@ static int isotp_send_first_frame(IsoTpLink* link, uint32_t id) {
(void) memcpy(message.as.first_frame.data, link->send_buffer, sizeof(message.as.first_frame.data));

/* send message */
ret = isotp_user_send_can(id, message.as.data_array.ptr, sizeof(message));
ret = isotp_user_send_can(id, message.as.data_array.ptr, sizeof(message)
#if defined (ISO_TP_USER_SEND_CAN_ARG)
,link->user_send_can_arg
#endif

);
if (ISOTP_RET_OK == ret) {
link->send_offset += sizeof(message.as.first_frame.data);
link->send_sn = 1;
Expand All @@ -108,6 +123,7 @@ static int isotp_send_consecutive_frame(IsoTpLink* link) {
IsoTpCanMessage message;
uint16_t data_length;
int ret;
uint8_t size = 0;

/* multi frame message length must greater than 7 */
assert(link->send_size > 7);
Expand All @@ -124,12 +140,18 @@ static int isotp_send_consecutive_frame(IsoTpLink* link) {
/* send message */
#ifdef ISO_TP_FRAME_PADDING
(void) memset(message.as.consecutive_frame.data + data_length, ISO_TP_FRAME_PADDING_VALUE, sizeof(message.as.consecutive_frame.data) - data_length);
ret = isotp_user_send_can(link->send_arbitration_id, message.as.data_array.ptr, sizeof(message));
size = sizeof(message);
#else
size = data_length + 1;
#endif

ret = isotp_user_send_can(link->send_arbitration_id,
message.as.data_array.ptr,
data_length + 1);
message.as.data_array.ptr, size
#if defined (ISO_TP_USER_SEND_CAN_ARG)
,link->user_send_can_arg
#endif
);

if (ISOTP_RET_OK == ret) {
link->send_offset += data_length;
if (++(link->send_sn) > 0x0F) {
Expand Down
4 changes: 4 additions & 0 deletions isotp.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ typedef struct IsoTpLink {
end at receive FC */
int receive_protocol_result;
uint8_t receive_status;

#if defined(ISO_TP_USER_SEND_CAN_ARG)
void* user_send_can_arg;
#endif
} IsoTpLink;

/**
Expand Down
5 changes: 5 additions & 0 deletions isotp_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,10 @@
#define ISO_TP_FRAME_PADDING_VALUE 0xAA
#endif

/* Private: Determines if by default, an additional argument is present in the
* definition of isotp_user_send_can.
*/
//#define ISO_TP_USER_SEND_CAN_ARG

#endif

6 changes: 5 additions & 1 deletion isotp_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ void isotp_user_debug(const char* message, ...);
* or ISOTP_RET_ERROR if transmission couldn't be completed
*/
int isotp_user_send_can(const uint32_t arbitration_id,
const uint8_t* data, const uint8_t size);
const uint8_t* data, const uint8_t size
#if ISO_TP_USER_SEND_CAN_ARG
,void *arg
#endif
);

/**
* @brief user implemented, gets the amount of time passed since the last call in microseconds
Expand Down
4 changes: 2 additions & 2 deletions vars.mk
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ CPPSTD := "c++0x"
###
LIB_NAME := "libisotp.so"
MAJOR_VER := "1"
MINOR_VER := "1"
REVISION := "1"
MINOR_VER := "2"
REVISION := "0"
OUTPUT_NAME := $(LIB_NAME).$(MAJOR_VER).$(MINOR_VER).$(REVISION)

###
Expand Down

0 comments on commit 276549c

Please sign in to comment.