summaryrefslogtreecommitdiffstats
path: root/low-can-binding
diff options
context:
space:
mode:
authorArthur Guyader <arthur.guyader@iot.bzh>2019-08-27 14:44:48 +0200
committerArthur Guyader <arthur.guyader@iot.bzh>2019-08-30 15:06:45 +0200
commitb8e8186c95f50e76aa4d88c3c751053568ab7cdf (patch)
treebd9e31008cd584fe5a8995e6338bd496ee25fedd /low-can-binding
parent7f038fed824cac9b747c033b441263512421c6b2 (diff)
Add feature ISO TP (multi frames and peer to peer)
This commit adds the ISO TP feature. The ISO TP protocol allows to communicate between two ECU. The protocol allows multi packets management. Bug-AGL : SPEC-2779 Change-Id: Ic222615b547f28e926930e6c1dea2c0265055afd Signed-off-by: Arthur Guyader <arthur.guyader@iot.bzh>
Diffstat (limited to 'low-can-binding')
-rw-r--r--low-can-binding/CMakeLists.txt10
-rw-r--r--low-can-binding/binding/application-generated.cpp182
-rw-r--r--low-can-binding/binding/low-can-cb.cpp116
-rw-r--r--low-can-binding/binding/low-can-subscription.cpp114
-rw-r--r--low-can-binding/binding/low-can-subscription.hpp13
-rw-r--r--low-can-binding/can/message-definition.cpp5
-rw-r--r--low-can-binding/can/message-definition.hpp1
-rw-r--r--low-can-binding/can/message/can-message.cpp5
-rw-r--r--low-can-binding/can/message/can-message.hpp11
-rw-r--r--low-can-binding/can/message/j1939-message.cpp6
-rw-r--r--low-can-binding/can/message/j1939-message.hpp1
-rw-r--r--low-can-binding/can/message/message.cpp13
-rw-r--r--low-can-binding/can/message/message.hpp10
-rw-r--r--low-can-binding/utils/socketcan-isotp.cpp191
-rw-r--r--low-can-binding/utils/socketcan-isotp.hpp39
-rw-r--r--low-can-binding/utils/socketcan.hpp3
16 files changed, 667 insertions, 53 deletions
diff --git a/low-can-binding/CMakeLists.txt b/low-can-binding/CMakeLists.txt
index 3c698c73..ada0e808 100644
--- a/low-can-binding/CMakeLists.txt
+++ b/low-can-binding/CMakeLists.txt
@@ -49,6 +49,14 @@ PROJECT_TARGET_ADD(low-can)
binding/application-generated.cpp
)
+
+ if(WITH_FEATURE_ISOTP)
+ set(SOURCES_ISOTP
+ utils/socketcan-isotp.cpp
+ )
+ endif()
+
+
if(WITH_FEATURE_J1939)
set(SOURCES_J1939
can/message/j1939-message.cpp
@@ -58,7 +66,7 @@ PROJECT_TARGET_ADD(low-can)
)
endif()
- add_library(${TARGET_NAME} MODULE ${SOURCES} ${SOURCES_J1939})
+ add_library(${TARGET_NAME} MODULE ${SOURCES} ${SOURCES_J1939} ${SOURCES_ISOTP})
set(OPENAPI_DEF "binding/low-can-apidef" CACHE STRING "name and path to the JSON API definition without extension")
# Binder exposes a unique public entry point
diff --git a/low-can-binding/binding/application-generated.cpp b/low-can-binding/binding/application-generated.cpp
index 47fdafa5..bd1837fc 100644
--- a/low-can-binding/binding/application-generated.cpp
+++ b/low-can-binding/binding/application-generated.cpp
@@ -449,6 +449,188 @@ application_t::application_t()
})}
} // end signals vector
})} // end message_definition entry
+#ifdef USE_FEATURE_ISOTP
+, {std::make_shared<message_definition_t>(message_definition_t{"ls",0x111,"",16,66,frequency_clock_t(5.00000f),true,
+ { // beginning signals vector
+ {std::make_shared<signal_t> (signal_t{
+ "sig1.1",// generic_name
+ 0,// bit_position
+ 16,// bit_size
+ 1.00000f,// factor
+ 0.00000f,// offset
+ 0,// min_value
+ 0,// max_value
+ frequency_clock_t(0.00000f),// frequency
+ true,// send_same
+ false,// force_send_changed
+ {
+ },// states
+ true,// writable
+ nullptr,// decoder
+ nullptr,// encoder
+ false,// received
+ std::make_pair<bool, int>(false, 0),// multiplex
+ 0,// is_big_endian
+ 0,// is_signed
+ ""// unit
+ })},
+ {std::make_shared<signal_t> (signal_t{
+ "sig1.2",// generic_name
+ 16,// bit_position
+ 16,// bit_size
+ 1.00000f,// factor
+ 0.00000f,// offset
+ 0,// min_value
+ 0,// max_value
+ frequency_clock_t(0.00000f),// frequency
+ true,// send_same
+ false,// force_send_changed
+ {
+ },// states
+ true,// writable
+ nullptr,// decoder
+ nullptr,// encoder
+ false,// received
+ std::make_pair<bool, int>(false, 0),// multiplex
+ 0,// is_big_endian
+ 0,// is_signed
+ ""// unit
+ })},
+ {std::make_shared<signal_t> (signal_t{
+ "sig2.1",// generic_name
+ 32,// bit_position
+ 16,// bit_size
+ 1.00000f,// factor
+ 0.00000f,// offset
+ 0,// min_value
+ 0,// max_value
+ frequency_clock_t(0.00000f),// frequency
+ true,// send_same
+ false,// force_send_changed
+ {
+ },// states
+ true,// writable
+ nullptr,// decoder
+ nullptr,// encoder
+ false,// received
+ std::make_pair<bool, int>(false, 0),// multiplex
+ 0,// is_big_endian
+ 0,// is_signed
+ ""// unit
+ })},
+ {std::make_shared<signal_t> (signal_t{
+ "sig2.2",// generic_name
+ 48,// bit_position
+ 16,// bit_size
+ 1.00000f,// factor
+ 0.00000f,// offset
+ 0,// min_value
+ 0,// max_value
+ frequency_clock_t(0.00000f),// frequency
+ true,// send_same
+ false,// force_send_changed
+ {
+ },// states
+ true,// writable
+ nullptr,// decoder
+ nullptr,// encoder
+ false,// received
+ std::make_pair<bool, int>(false, 0),// multiplex
+ 0,// is_big_endian
+ 0,// is_signed
+ ""// unit
+ })},
+ {std::make_shared<signal_t> (signal_t{
+ "sig3.1",// generic_name
+ 64,// bit_position
+ 16,// bit_size
+ 1.00000f,// factor
+ 0.00000f,// offset
+ 0,// min_value
+ 0,// max_value
+ frequency_clock_t(0.00000f),// frequency
+ true,// send_same
+ false,// force_send_changed
+ {
+ },// states
+ true,// writable
+ nullptr,// decoder
+ nullptr,// encoder
+ false,// received
+ std::make_pair<bool, int>(false, 0),// multiplex
+ 0,// is_big_endian
+ 0,// is_signed
+ ""// unit
+ })},
+ {std::make_shared<signal_t> (signal_t{
+ "sig3.2",// generic_name
+ 80,// bit_position
+ 16,// bit_size
+ 1.00000f,// factor
+ 0.00000f,// offset
+ 0,// min_value
+ 0,// max_value
+ frequency_clock_t(0.00000f),// frequency
+ true,// send_same
+ false,// force_send_changed
+ {
+ },// states
+ true,// writable
+ nullptr,// decoder
+ nullptr,// encoder
+ false,// received
+ std::make_pair<bool, int>(false, 0),// multiplex
+ 0,// is_big_endian
+ 0,// is_signed
+ ""// unit
+ })},
+ {std::make_shared<signal_t> (signal_t{
+ "sig4.1",// generic_name
+ 96,// bit_position
+ 16,// bit_size
+ 1.00000f,// factor
+ 0.00000f,// offset
+ 0,// min_value
+ 0,// max_value
+ frequency_clock_t(0.00000f),// frequency
+ true,// send_same
+ false,// force_send_changed
+ {
+ },// states
+ true,// writable
+ nullptr,// decoder
+ nullptr,// encoder
+ false,// received
+ std::make_pair<bool, int>(false, 0),// multiplex
+ 0,// is_big_endian
+ 0,// is_signed
+ ""// unit
+ })},
+ {std::make_shared<signal_t> (signal_t{
+ "sig4.2",// generic_name
+ 112,// bit_position
+ 16,// bit_size
+ 1.00000f,// factor
+ 0.00000f,// offset
+ 0,// min_value
+ 0,// max_value
+ frequency_clock_t(0.00000f),// frequency
+ true,// send_same
+ false,// force_send_changed
+ {
+ },// states
+ true,// writable
+ nullptr,// decoder
+ nullptr,// encoder
+ false,// received
+ std::make_pair<bool, int>(false, 0),// multiplex
+ 0,// is_big_endian
+ 0,// is_signed
+ ""// unit
+ })}
+ } // end signals vector
+ })} // end message_definition entry
+#endif
#ifdef USE_FEATURE_J1939
, {std::make_shared<message_definition_t>(message_definition_t{"j1939",61442,"ETC1",8,18,frequency_clock_t(5.00000f),true,
{ // beginning signals vector
diff --git a/low-can-binding/binding/low-can-cb.cpp b/low-can-binding/binding/low-can-cb.cpp
index c677b172..2c6e2be3 100644
--- a/low-can-binding/binding/low-can-cb.cpp
+++ b/low-can-binding/binding/low-can-cb.cpp
@@ -334,6 +334,12 @@ static event_filter_t generate_filter(json_object* args)
if (json_object_object_get_ex(filter, "max", &obj)
&& (json_object_is_type(obj, json_type_double) || json_object_is_type(obj, json_type_int)))
{event_filter.max = (float)json_object_get_double(obj);}
+ if (json_object_object_get_ex(filter, "rx_id", &obj)
+ && (json_object_is_type(obj, json_type_int)))
+ {event_filter.rx_id = (canid_t) json_object_get_int(obj);}
+ if (json_object_object_get_ex(filter, "tx_id", &obj)
+ && (json_object_is_type(obj, json_type_int)))
+ {event_filter.tx_id = (canid_t) json_object_get_int(obj);}
}
return event_filter;
}
@@ -515,7 +521,7 @@ static int send_frame(struct canfd_frame& cfd, const std::string& bus_name, sock
}
}
*/
-static int send_message(message_t *message, const std::string& bus_name, uint32_t flags)
+static int send_message(message_t *message, const std::string& bus_name, uint32_t flags, event_filter_t &event_filter, std::shared_ptr<signal_t> signal)
{
if(bus_name.empty())
{
@@ -526,14 +532,22 @@ static int send_message(message_t *message, const std::string& bus_name, uint32_
if( cd.count(bus_name) == 0)
{
- cd[bus_name] = std::make_shared<low_can_subscription_t>(low_can_subscription_t());
+ cd[bus_name] = std::make_shared<low_can_subscription_t>(low_can_subscription_t(event_filter));
}
+ cd[bus_name]->set_signal(signal);
+
if(flags&BCM_PROTOCOL)
{
return low_can_subscription_t::tx_send(*cd[bus_name], message, bus_name);
}
+#ifdef USE_FEATURE_ISOTP
+ else if(flags&ISOTP_PROTOCOL)
+ {
+ return low_can_subscription_t::isotp_send(*cd[bus_name], message, bus_name);
+ }
+#endif
#ifdef USE_FEATURE_J1939
else if(flags&J1939_PROTOCOL)
{
@@ -547,7 +561,8 @@ static int send_message(message_t *message, const std::string& bus_name, uint32_
}
-static void write_raw_frame(afb_req_t request, const std::string& bus_name, message_t *message, struct json_object *can_data, uint32_t flags)
+static void write_raw_frame(afb_req_t request, const std::string& bus_name, message_t *message,
+ struct json_object *can_data, uint32_t flags, event_filter_t &event_filter)
{
struct utils::signals_found sf;
@@ -570,17 +585,22 @@ static void write_raw_frame(afb_req_t request, const std::string& bus_name, mess
AFB_DEBUG("CAN_MAX_DLEN");
message->set_maxdlen(CAN_MAX_DLEN);
}
+
+ if(sf.signals[0]->get_message()->is_isotp())
+ {
+ flags = ISOTP_PROTOCOL;
+ message->set_maxdlen(MAX_ISOTP_FRAMES * message->get_maxdlen());
+ }
+ }
+
+#ifdef USE_FEATURE_J1939
+ if(flags&J1939_PROTOCOL)
+ {
+ message->set_maxdlen(J1939_MAX_DLEN);
}
+#endif
- if((message->get_length()> 0 && (
- ((flags&BCM_PROTOCOL) && (
- (message->get_length() <= CANFD_MAX_DLEN * MAX_BCM_CAN_FRAMES && message->get_flags() & CAN_FD_FRAME)
- || (message->get_length() <= CAN_MAX_DLEN * MAX_BCM_CAN_FRAMES && !(message->get_flags() & CAN_FD_FRAME))
- ))
- #ifdef USE_FEATURE_J1939
- || (message->get_length() <= J1939_MAX_DLEN && flags&J1939_PROTOCOL)
- #endif
- )))
+ if(message->get_length() > 0 && message->get_length() <= message->get_maxdlen())
{
std::vector<uint8_t> data;
for (int i = 0 ; i < message->get_length() ; i++)
@@ -601,6 +621,10 @@ static void write_raw_frame(afb_req_t request, const std::string& bus_name, mess
{
afb_req_fail(request, "Invalid", "Frame J1939");
}
+ else if(flags&ISOTP_PROTOCOL)
+ {
+ afb_req_fail(request, "Invalid", "Frame ISOTP");
+ }
else
{
afb_req_fail(request, "Invalid", "Frame");
@@ -608,7 +632,7 @@ static void write_raw_frame(afb_req_t request, const std::string& bus_name, mess
return;
}
- if(! send_message(message, application_t::instance().get_can_bus_manager().get_can_device_name(bus_name),flags))
+ if(! send_message(message, application_t::instance().get_can_bus_manager().get_can_device_name(bus_name), flags, event_filter, sf.signals[0]))
{
afb_req_success(request, nullptr, "Message correctly sent");
}
@@ -624,7 +648,7 @@ static void write_raw_frame(afb_req_t request, const std::string& bus_name, mess
}
-static void write_frame(afb_req_t request, const std::string& bus_name, json_object *json_value)
+static void write_frame(afb_req_t request, const std::string& bus_name, json_object *json_value, event_filter_t &event_filter)
{
message_t *message;
int id;
@@ -640,7 +664,7 @@ static void write_frame(afb_req_t request, const std::string& bus_name, json_obj
"can_data", &can_data))
{
message = new can_message_t(0,(uint32_t)id,(uint32_t)length,false,0,data,0);
- write_raw_frame(request,bus_name,message,can_data,BCM_PROTOCOL);
+ write_raw_frame(request,bus_name,message,can_data,BCM_PROTOCOL,event_filter);
}
#ifdef USE_FEATURE_J1939
else if(!wrap_json_unpack(json_value, "{si, si, so !}",
@@ -649,7 +673,7 @@ static void write_frame(afb_req_t request, const std::string& bus_name, json_obj
"data", &can_data))
{
message = new j1939_message_t((uint32_t)length,data,0,J1939_NO_NAME,(pgn_t)id,J1939_NO_ADDR);
- write_raw_frame(request,bus_name,message,can_data,J1939_PROTOCOL);
+ write_raw_frame(request,bus_name,message,can_data,J1939_PROTOCOL, event_filter);
}
#endif
else
@@ -660,7 +684,7 @@ static void write_frame(afb_req_t request, const std::string& bus_name, json_obj
delete message;
}
-static void write_signal(afb_req_t request, const std::string& name, json_object *json_value)
+static void write_signal(afb_req_t request, const std::string& name, json_object *json_value, event_filter_t &event_filter)
{
struct canfd_frame cfd;
struct utils::signals_found sf;
@@ -679,7 +703,7 @@ static void write_signal(afb_req_t request, const std::string& name, json_object
return;
}
- std::shared_ptr<signal_t>& sig = sf.signals[0];
+ std::shared_ptr<signal_t> sig = sf.signals[0];
if(! sig->get_writable())
{
afb_req_fail_f(request, "%s isn't writable. Message not sent.", sig->get_name().c_str());
@@ -696,6 +720,10 @@ static void write_signal(afb_req_t request, const std::string& name, json_object
{
flags = J1939_PROTOCOL;
}
+ else if(sig->get_message()->is_isotp())
+ {
+ flags = ISOTP_PROTOCOL;
+ }
else
{
flags = BCM_PROTOCOL;
@@ -704,7 +732,7 @@ static void write_signal(afb_req_t request, const std::string& name, json_object
// cfd = encoder_t::build_frame(sig, value);
message_t *message = encoder_t::build_message(sig,value,false,false);
- if(! send_message(message, sig->get_message()->get_bus_device_name(), flags) && send)
+ if(! send_message(message, sig->get_message()->get_bus_device_name(), flags, event_filter, sig) && send)
{
afb_req_success(request, nullptr, "Message correctly sent");
}
@@ -727,25 +755,43 @@ static void write_signal(afb_req_t request, const std::string& name, json_object
void write(afb_req_t request)
{
- struct json_object* args = nullptr, *json_value = nullptr;
- const char *name = nullptr;
-
+ struct json_object* args = nullptr, *json_value = nullptr, *name = nullptr;
args = afb_req_json(request);
- // Process about Raw CAN message on CAN bus directly
- if (args != NULL && ! wrap_json_unpack(args, "{ss, so !}",
- "bus_name", &name,
- "frame", &json_value))
- write_frame(request, name, json_value);
-
- // Search signal then encode value.
- else if(args != NULL &&
- ! wrap_json_unpack(args, "{ss, so !}",
- "signal_name", &name,
- "signal_value", &json_value))
- write_signal(request, std::string(name), json_value);
+ if(args != NULL)
+ {
+ event_filter_t event_filter = generate_filter(args);
+
+ if(json_object_object_get_ex(args,"bus_name",&name))
+ {
+ if(json_object_object_get_ex(args,"frame",&json_value))
+ {
+ write_frame(request, (std::string)json_object_get_string(name), json_value, event_filter);
+ }
+ else
+ {
+ afb_req_fail(request, "Error", "Request argument malformed");
+ }
+ }
+ else if(json_object_object_get_ex(args,"signal_name",&name))
+ {
+ if(json_object_object_get_ex(args,"signal_value",&json_value))
+ {
+ write_signal(request, (std::string)json_object_get_string(name), json_value, event_filter);
+ }
+ else
+ {
+ afb_req_fail(request, "Error", "Request argument malformed");
+ }
+ }
+ else {
+ afb_req_fail(request, "Error", "Request argument malformed");
+ }
+ }
else
- afb_req_fail(request, "Error", "Request argument malformed");
+ {
+ afb_req_fail(request, "Error", "Request argument null");
+ }
}
static struct json_object *get_signals_value(const std::string& name)
diff --git a/low-can-binding/binding/low-can-subscription.cpp b/low-can-binding/binding/low-can-subscription.cpp
index 0f4bf0c9..6d02b101 100644
--- a/low-can-binding/binding/low-can-subscription.cpp
+++ b/low-can-binding/binding/low-can-subscription.cpp
@@ -22,6 +22,10 @@
#include "../utils/socketcan-bcm.hpp"
#include "../can/can-encoder.hpp"
+#ifdef USE_FEATURE_ISOTP
+#include "../utils/socketcan-isotp.hpp"
+#endif
+
#ifdef USE_FEATURE_J1939
#include "../utils/socketcan-j1939/socketcan-j1939-data.hpp"
#endif
@@ -212,6 +216,16 @@ float low_can_subscription_t::get_max() const
return event_filter_.max;
}
+canid_t low_can_subscription_t::get_rx_id() const
+{
+ return event_filter_.rx_id;
+}
+
+canid_t low_can_subscription_t::get_tx_id() const
+{
+ return event_filter_.tx_id;
+}
+
std::shared_ptr<utils::socketcan_t> low_can_subscription_t::get_socket()
{
return socket_;
@@ -232,11 +246,27 @@ void low_can_subscription_t::set_max(float max)
event_filter_.max = max;
}
+void low_can_subscription_t::set_rx_id(canid_t rx_id)
+{
+ event_filter_.rx_id = rx_id;
+}
+
+void low_can_subscription_t::set_tx_id(canid_t tx_id)
+{
+ event_filter_.tx_id = tx_id;
+}
+
void low_can_subscription_t::set_index(int index)
{
index_ = index;
}
+void low_can_subscription_t::set_signal(std::shared_ptr<signal_t> signal)
+{
+ signal_ = signal;
+}
+
+
/// @brief Based upon which object is a subscribed CAN signal or diagnostic message
/// it will open the socket with the required CAN bus device name.
///
@@ -265,6 +295,36 @@ int low_can_subscription_t::open_socket(low_can_subscription_t &subscription, co
}
subscription.index_ = (int)subscription.socket_->socket();
}
+#ifdef USE_FEATURE_ISOTP
+ else if(flags&ISOTP_PROTOCOL)
+ {
+ if(subscription.signal_ != nullptr)
+ {
+ canid_t rx = NO_CAN_ID;
+ canid_t tx = NO_CAN_ID;
+ if(flags&ISOTP_SEND)
+ {
+ rx = subscription.get_rx_id();
+ tx = subscription.signal_->get_message()->get_id();
+ }
+ else if(flags&ISOTP_RECEIVE)
+ {
+ rx = subscription.signal_->get_message()->get_id();
+ tx = subscription.get_tx_id();
+ }
+ std::shared_ptr<utils::socketcan_isotp_t> socket = std::make_shared<utils::socketcan_isotp_t>();
+ ret = socket->open(subscription.signal_->get_message()->get_bus_device_name(),rx,tx);
+ subscription.socket_ = socket;
+ }
+ else if(!bus_name.empty())
+ {
+ std::shared_ptr<utils::socketcan_isotp_t> socket = std::make_shared<utils::socketcan_isotp_t>();
+ ret = socket->open(bus_name, subscription.get_rx_id(),subscription.get_tx_id());
+ subscription.socket_ = socket;
+ }
+ subscription.index_ = (int)subscription.socket_->socket();
+ }
+#endif
#ifdef USE_FEATURE_J1939
else if(flags&J1939_ADDR_CLAIM_PROTOCOL)
{
@@ -374,6 +434,18 @@ int low_can_subscription_t::create_rx_filter_j1939(low_can_subscription_t &subsc
}
#endif
+int low_can_subscription_t::create_rx_filter_isotp(low_can_subscription_t &subscription, std::shared_ptr<signal_t> sig)
+{
+ subscription.signal_= sig;
+
+ // Make sure that socket is opened.
+ if(open_socket(subscription,"",ISOTP_PROTOCOL|ISOTP_RECEIVE) < 0)
+ {
+ return -1;
+ }
+ return 0;
+}
+
/// @brief Create a RX_SETUP receive job to be used by the BCM socket for a CAN signal
/// subscription
///
@@ -462,18 +534,27 @@ int low_can_subscription_t::create_rx_filter_can(low_can_subscription_t &subscri
int low_can_subscription_t::create_rx_filter(std::shared_ptr<signal_t> sig)
{
- #ifdef USE_FEATURE_J1939
- if(sig->get_message()->is_j1939())
+ if(!sig->get_message()->is_isotp() && !sig->get_message()->is_j1939())
+ {
+ return low_can_subscription_t::create_rx_filter_can(*this, sig);
+ }
+#ifdef USE_FEATURE_ISOTP
+ else if(sig->get_message()->is_isotp())
+ {
+ return low_can_subscription_t::create_rx_filter_isotp(*this,sig);
+ }
+#endif
+#ifdef USE_FEATURE_J1939
+ else if(sig->get_message()->is_j1939())
{
return low_can_subscription_t::create_rx_filter_j1939(*this, sig);
}
+#endif
else
{
- #endif
- return low_can_subscription_t::create_rx_filter_can(*this, sig);
- #ifdef USE_FEATURE_J1939
+ AFB_ERROR("Signal can't be j1939 and isotp");
+ return -1;
}
- #endif
}
@@ -607,3 +688,24 @@ int low_can_subscription_t::j1939_send(low_can_subscription_t &subscription, mes
return 0;
}
#endif
+
+
+int low_can_subscription_t::isotp_send(low_can_subscription_t &subscription, message_t *message, const std::string& bus_name)
+{
+ //struct bcm_msg bcm_msg = subscription.make_bcm_head(TX_SEND, cfd.can_id);
+ //subscription.add_one_bcm_frame(cfd, bcm_msg);
+
+ if(subscription.open_socket(subscription, bus_name, ISOTP_PROTOCOL|ISOTP_SEND) < 0)
+ {
+ return -1;
+ }
+
+ can_message_t *cm = static_cast<can_message_t*>(message);
+ if(subscription.socket_->write_message(*cm) < 0)
+ {
+ AFB_ERROR("Error write iso tp message");
+ return -1;
+ }
+
+ return 0;
+} \ No newline at end of file
diff --git a/low-can-binding/binding/low-can-subscription.hpp b/low-can-binding/binding/low-can-subscription.hpp
index b152e4b2..3f2c3acd 100644
--- a/low-can-binding/binding/low-can-subscription.hpp
+++ b/low-can-binding/binding/low-can-subscription.hpp
@@ -35,10 +35,12 @@ struct event_filter_t
float frequency; ///< frequency - Maximum frequency which will be received and pushed to a subscribed event.
float min; ///< min - Minimum value that the signal doesn't have to go below to be pushed.
float max; ///< max - Maximum value that the signal doesn't have to go above to be pushed.
+ canid_t rx_id;
+ canid_t tx_id;
- event_filter_t() : frequency{0}, min{-__FLT_MAX__}, max{__FLT_MAX__} {};
+ event_filter_t() : frequency{0}, min{-__FLT_MAX__}, max{__FLT_MAX__}, rx_id{NO_CAN_ID}, tx_id{NO_CAN_ID} {};
bool operator==(const event_filter_t& ext) const {
- return frequency == ext.frequency && min == ext.min && max == ext.max;
+ return frequency == ext.frequency && min == ext.min && max == ext.max && rx_id == ext.rx_id && tx_id == ext.tx_id;
}
};
@@ -84,12 +86,17 @@ public:
float get_frequency() const;
float get_min() const;
float get_max() const;
+ canid_t get_rx_id() const;
+ canid_t get_tx_id() const;
std::shared_ptr<utils::socketcan_t> get_socket();
void set_frequency(float freq);
void set_min(float min);
void set_max(float max);
void set_index(int index);
+ void set_rx_id(canid_t rx_id);
+ void set_tx_id(canid_t tx_id);
+ void set_signal(std::shared_ptr<signal_t> signal);
static struct bcm_msg make_bcm_head(uint32_t opcode, uint32_t can_id = 0, uint32_t flags = 0, const struct timeval& timeout = {0,0}, const struct timeval& frequency_thinning = {0,0});
static void add_one_bcm_frame(struct canfd_frame& cfd, struct bcm_msg& bcm_msg);
@@ -101,8 +108,10 @@ public:
int create_rx_filter(std::shared_ptr<diagnostic_message_t> sig);
static int create_rx_filter_can(low_can_subscription_t &subscription, std::shared_ptr<signal_t> sig);
static int create_rx_filter_j1939(low_can_subscription_t &subscription, std::shared_ptr<signal_t> sig);
+ static int create_rx_filter_isotp(low_can_subscription_t &subscription, std::shared_ptr<signal_t> sig);
static int create_rx_filter_bcm(low_can_subscription_t &subscription, bcm_msg& bcm_msg);
static int tx_send(low_can_subscription_t &subscription, message_t *message, const std::string& bus_name);
static int j1939_send(low_can_subscription_t &subscription, message_t *message, const std::string& bus_name);
+ static int isotp_send(low_can_subscription_t &subscription, message_t *message, const std::string& bus_name);
};
diff --git a/low-can-binding/can/message-definition.cpp b/low-can-binding/can/message-definition.cpp
index 407ad750..a875dafa 100644
--- a/low-can-binding/can/message-definition.cpp
+++ b/low-can-binding/can/message-definition.cpp
@@ -77,6 +77,11 @@ bool message_definition_t::is_j1939() const
return (flags_&J1939_PROTOCOL);
}
+bool message_definition_t::is_isotp() const
+{
+ return (flags_&ISOTP_PROTOCOL);
+}
+
std::vector<std::shared_ptr<signal_t>>& message_definition_t::get_signals()
{
return signals_;
diff --git a/low-can-binding/can/message-definition.hpp b/low-can-binding/can/message-definition.hpp
index 13ae2289..f46d3adb 100644
--- a/low-can-binding/can/message-definition.hpp
+++ b/low-can-binding/can/message-definition.hpp
@@ -82,6 +82,7 @@ public:
uint32_t get_id() const;
bool is_fd() const;
bool is_j1939() const;
+ bool is_isotp() const;
std::vector<std::shared_ptr<signal_t>>& get_signals();
uint32_t get_length() const;
uint32_t get_flags() const;
diff --git a/low-can-binding/can/message/can-message.cpp b/low-can-binding/can/message/can-message.cpp
index 0ef693c7..b274206b 100644
--- a/low-can-binding/can/message/can-message.cpp
+++ b/low-can-binding/can/message/can-message.cpp
@@ -55,6 +55,11 @@ uint32_t can_message_t::get_id() const
}
+void can_message_t::set_id(const canid_t id)
+{
+ id_ = id;
+}
+
/// @brief Control whether the object is correctly initialized
/// to be sent over the CAN bus
///
diff --git a/low-can-binding/can/message/can-message.hpp b/low-can-binding/can/message/can-message.hpp
index 769899ea..acc3bfc1 100644
--- a/low-can-binding/can/message/can-message.hpp
+++ b/low-can-binding/can/message/can-message.hpp
@@ -39,8 +39,16 @@ class can_message_t : public message_t {
public:
can_message_t();
- can_message_t(uint32_t maxdlen, uint32_t id, uint32_t length, bool rtr_flag_, uint32_t flags, std::vector<uint8_t>& data, uint64_t timestamp);
+ can_message_t( uint32_t maxdlen,
+ uint32_t id,
+ uint32_t length,
+ bool rtr_flag_,
+ uint32_t flags,
+ std::vector<uint8_t>& data,
+ uint64_t timestamp);
+
uint32_t get_id() const;
+ void set_id(const canid_t id);
static std::shared_ptr<can_message_t> convert_from_frame(const canfd_frame& frame, size_t nbytes, uint64_t timestamp);
struct canfd_frame convert_to_canfd_frame();
@@ -53,5 +61,4 @@ class can_message_t : public message_t {
void set_bcm_msg(struct bcm_msg bcm_msg);
std::string get_debug_message();
-
};
diff --git a/low-can-binding/can/message/j1939-message.cpp b/low-can-binding/can/message/j1939-message.cpp
index ec65cba4..8e056c17 100644
--- a/low-can-binding/can/message/j1939-message.cpp
+++ b/low-can-binding/can/message/j1939-message.cpp
@@ -159,6 +159,12 @@ uint32_t j1939_message_t::get_id() const
return get_pgn();
}
+void j1939_message_t::set_id(const canid_t id)
+{
+ pgn_ = id;
+}
+
+
/**
* @brief Return the sockname of the message
*
diff --git a/low-can-binding/can/message/j1939-message.hpp b/low-can-binding/can/message/j1939-message.hpp
index 9e9cea4a..a513e94e 100644
--- a/low-can-binding/can/message/j1939-message.hpp
+++ b/low-can-binding/can/message/j1939-message.hpp
@@ -75,6 +75,7 @@ class j1939_message_t : public message_t
bool is_set();
std::string get_debug_message();
uint32_t get_id() const;
+ void set_id(const canid_t id);
struct sockaddr_can get_sockname();
void set_sockname(struct sockaddr_can sockname);
void set_sockname(pgn_t pgn, name_t name, uint8_t addr);
diff --git a/low-can-binding/can/message/message.cpp b/low-can-binding/can/message/message.cpp
index aaab99f5..2496b672 100644
--- a/low-can-binding/can/message/message.cpp
+++ b/low-can-binding/can/message/message.cpp
@@ -135,7 +135,7 @@ uint32_t message_t::get_length() const
*
* @param data A vector of data
*/
-void message_t::set_data(std::vector<uint8_t> &data)
+void message_t::set_data(std::vector<uint8_t> data)
{
data_ = data;
}
@@ -170,13 +170,22 @@ void message_t::set_flags(uint32_t flags)
flags_ = flags_ | flags;
}
+void message_t::erase_flags()
+{
+ flags_ = 0;
+}
+
uint32_t message_t::get_maxdlen()
{
return maxdlen_;
}
-
void message_t::set_maxdlen(uint32_t maxdlen)
{
maxdlen_ = maxdlen;
+}
+
+void message_t::set_length(uint32_t length)
+{
+ length_ = length;
} \ No newline at end of file
diff --git a/low-can-binding/can/message/message.hpp b/low-can-binding/can/message/message.hpp
index 6cef0185..db06eb38 100644
--- a/low-can-binding/can/message/message.hpp
+++ b/low-can-binding/can/message/message.hpp
@@ -29,6 +29,7 @@
#define CAN_MESSAGE_SIZE 8
#define MAX_BCM_CAN_FRAMES 257
+#define MAX_ISOTP_FRAMES 4096
/**
@@ -42,6 +43,8 @@
#define J1939_PROTOCOL 0x0010
#define J1939_ADDR_CLAIM_PROTOCOL 0x0020
#define ISOTP_PROTOCOL 0x0040
+#define ISOTP_SEND 0x0080
+#define ISOTP_RECEIVE 0x0100
#define FD_FRAME 0x0800
/// @class message_t
@@ -69,16 +72,17 @@ public:
uint32_t get_length() const;
uint64_t get_timestamp() const;
- void set_data(std::vector<uint8_t> &data);
+ void set_data(std::vector<uint8_t> data);
void set_sub_id(int sub_id);
void set_timestamp(uint64_t timestamp);
virtual bool is_set() = 0;
virtual std::string get_debug_message() = 0;
virtual uint32_t get_id() const = 0;
+ virtual void set_id(canid_t id) = 0;
uint32_t get_flags();
void set_flags(uint32_t flags);
+ void erase_flags();
uint32_t get_maxdlen();
void set_maxdlen(uint32_t maxdlen);
-
-
+ void set_length(uint32_t length);
};
diff --git a/low-can-binding/utils/socketcan-isotp.cpp b/low-can-binding/utils/socketcan-isotp.cpp
new file mode 100644
index 00000000..1aab9afa
--- /dev/null
+++ b/low-can-binding/utils/socketcan-isotp.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2019, 2020 "IoT.bzh"
+ * Author "Arthur Guyader" <arthur.guyader@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "socketcan-isotp.hpp"
+
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "../utils/converter.hpp"
+#include "../binding/application.hpp"
+
+namespace utils
+{
+ /**
+ * @brief Open ISOTP socket this default function will not work, because
+ * isotp need rx_id and tx_id
+ *
+ * @param device_name The device name where to open socket
+ * @return int -1 fail
+ */
+ int socketcan_isotp_t::open(std::string device_name)
+ {
+ AFB_WARNING("NOT USE THIS FUNCTION !");
+ return open(device_name,NO_CAN_ID,NO_CAN_ID);
+ }
+
+ /**
+ * @brief Open ISOTP socket, the socket will be open and bind
+ * with rx_id and tx_id
+ *
+ * @param device_name The device name where to open socket
+ * @param rx_id The source can_id
+ * @param tx_id The destination can_id
+ * @return int 0 if ok else -1
+ */
+ int socketcan_isotp_t::open(std::string device_name, canid_t rx_id, canid_t tx_id)
+ {
+ close();
+ socket_ = socketcan_t::open(PF_CAN, SOCK_DGRAM, CAN_ISOTP);
+
+ if(socket_ < 0)
+ {
+ AFB_ERROR("Error open ISO TP socket");
+ return -1;
+ }
+
+ if(define_tx_address(device_name,rx_id,tx_id) < 0)
+ {
+ return -1;
+ }
+
+ struct can_isotp_options opts;
+ memset(&opts,0,sizeof(opts));
+ setopt(SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
+
+ if(bind((struct sockaddr *)&tx_address_, sizeof(tx_address_)) < 0)
+ {
+ AFB_ERROR("Bind failed. %s", strerror(errno));
+ close();
+ return -1;
+ }
+
+ return socket_;
+ }
+
+ /**
+ * @brief Allows to read message
+ *
+ * @return std::shared_ptr<message_t> The message that was read
+ */
+ std::shared_ptr<message_t> socketcan_isotp_t::read_message()
+ {
+
+ std::shared_ptr<can_message_t> cm = std::make_shared<can_message_t>();
+ uint8_t msg[MAX_ISOTP_FRAMES];
+ ssize_t nbytes = read(socket(),msg,MAX_ISOTP_FRAMES);
+
+ cm->set_id(tx_address_.can_addr.tp.rx_id);
+
+ if(nbytes < 0)
+ {
+ AFB_ERROR("Can't read the next message from socket '%d'. '%s'", socket(), strerror(errno));
+ return cm;
+ }
+
+ std::vector<uint8_t> data;
+ for (int i=0; i < nbytes; i++)
+ {
+ data.push_back(msg[i]);
+ }
+
+ std::string data_string;
+ data_string = converter_t::to_hex(msg,nbytes);
+ AFB_DEBUG("DATA ISO TP for id : %x = %s",cm->get_id(),data_string.c_str());
+
+
+ cm->set_data(data);
+ cm->erase_flags();
+ cm->set_flags(ISOTP_PROTOCOL);
+ cm->set_length((uint32_t)nbytes);
+ cm->set_sub_id((int)socket());
+ // Need to define behaviour
+
+ return cm;
+ }
+
+ /**
+ * @brief Allows to write can message
+ *
+ * @param m The message to send
+ * @return int 0 if ok else -1
+ */
+ int socketcan_isotp_t::write_message(message_t& m)
+ {
+ size_t size = m.get_length();
+ if(size < MAX_ISOTP_FRAMES)
+ {
+ ssize_t ret = write(socket(),m.get_data(),size);
+ if(ret < 0)
+ {
+ AFB_ERROR("Error sending : %i %s", errno, ::strerror(errno));
+ return -1;
+ }
+
+ if(ret != size)
+ {
+ AFB_WARNING("ISOTP wrote only %zd byte",ret);
+ }
+ }
+ else
+ {
+ AFB_ERROR("Error sending too much data");
+ return -1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * @brief Define the tx address for the bind function
+ *
+ * @param device_name The device can that you want to bind
+ * @param rx_id The source can_id
+ * @param tx_id The destination can_id
+ * @return int 0 if ok else -1
+ */
+ int socketcan_isotp_t::define_tx_address(std::string device_name, canid_t rx_id, canid_t tx_id)
+ {
+ struct ifreq ifr;
+ ::strcpy(ifr.ifr_name, device_name.c_str());
+ AFB_DEBUG("ifr_name is : %s", ifr.ifr_name);
+
+ if(::ioctl(socket_, SIOCGIFINDEX, &ifr) < 0)
+ {
+ AFB_ERROR("ioctl failed. Error was : %s", strerror(errno));
+ close();
+ }
+ else
+ {
+ tx_address_.can_ifindex = ifr.ifr_ifindex;
+ }
+
+ tx_address_.can_family = AF_CAN;
+
+ if(tx_id == NO_CAN_ID || rx_id == NO_CAN_ID)
+ {
+ AFB_ERROR("Error tx_id or rx_id");
+ return -1;
+ }
+
+ tx_address_.can_addr.tp.rx_id = rx_id;
+ tx_address_.can_addr.tp.tx_id = tx_id;
+
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/low-can-binding/utils/socketcan-isotp.hpp b/low-can-binding/utils/socketcan-isotp.hpp
new file mode 100644
index 00000000..86ed9faf
--- /dev/null
+++ b/low-can-binding/utils/socketcan-isotp.hpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019, 2020 "IoT.bzh"
+ * Author "Arthur Guyader" <arthur.guyader@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <linux/can/isotp.h>
+#include "socketcan.hpp"
+#include "../can/message/can-message.hpp"
+
+#define CAN_ISOTP_MAX_DLEN 4096
+
+namespace utils
+{
+ class socketcan_isotp_t : public socketcan_t
+ {
+ public:
+ using socketcan_t::socketcan_t;
+
+ virtual int open(std::string device_name);
+ virtual int open(std::string device_name, canid_t rx_id, canid_t tx_id);
+ virtual std::shared_ptr<message_t> read_message();
+ virtual int write_message(message_t& obj);
+ int define_tx_address(std::string device_name, canid_t rx_id, canid_t tx_id);
+ };
+} \ No newline at end of file
diff --git a/low-can-binding/utils/socketcan.hpp b/low-can-binding/utils/socketcan.hpp
index 6391d011..a3b31591 100644
--- a/low-can-binding/utils/socketcan.hpp
+++ b/low-can-binding/utils/socketcan.hpp
@@ -27,6 +27,7 @@
#include "../can/message/can-message.hpp"
#define INVALID_SOCKET -1
+#define NO_CAN_ID 0xFFFFFFFFU
namespace utils
{
@@ -58,6 +59,4 @@ namespace utils
int bind(const struct sockaddr* addr, socklen_t len);
int connect(const struct sockaddr* addr, socklen_t len);
};
-
-
}