aboutsummaryrefslogtreecommitdiffstats
path: root/low-can-binding
diff options
context:
space:
mode:
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);
};
-
-
}