From 22b1864b72c2520fbc9d4e3d3332c28916b5a9ed Mon Sep 17 00:00:00 2001 From: Romain Forlot Date: Tue, 26 Nov 2019 16:19:38 +0100 Subject: 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 Bug-AGL: SPEC-2976 Change-Id: Ic222615b547f28e926930e6c1dea2c0265055afd Signed-off-by: Arthur Guyader Signed-off-by: Romain Forlot --- low-can-binding/binding/application-generated.cpp | 182 ++++++++++++++++++++++ low-can-binding/binding/low-can-cb.cpp | 116 +++++++++----- low-can-binding/binding/low-can-subscription.cpp | 114 +++++++++++++- low-can-binding/binding/low-can-subscription.hpp | 13 +- 4 files changed, 382 insertions(+), 43 deletions(-) (limited to 'low-can-binding/binding') 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{"ls",0x111,"",16,66,frequency_clock_t(5.00000f),true, + { // beginning signals vector + {std::make_shared (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(false, 0),// multiplex + 0,// is_big_endian + 0,// is_signed + ""// unit + })}, + {std::make_shared (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(false, 0),// multiplex + 0,// is_big_endian + 0,// is_signed + ""// unit + })}, + {std::make_shared (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(false, 0),// multiplex + 0,// is_big_endian + 0,// is_signed + ""// unit + })}, + {std::make_shared (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(false, 0),// multiplex + 0,// is_big_endian + 0,// is_signed + ""// unit + })}, + {std::make_shared (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(false, 0),// multiplex + 0,// is_big_endian + 0,// is_signed + ""// unit + })}, + {std::make_shared (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(false, 0),// multiplex + 0,// is_big_endian + 0,// is_signed + ""// unit + })}, + {std::make_shared (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(false, 0),// multiplex + 0,// is_big_endian + 0,// is_signed + ""// unit + })}, + {std::make_shared (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(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{"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) { 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()); + cd[bus_name] = std::make_shared(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 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& sig = sf.signals[0]; + std::shared_ptr 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 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) +{ + 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 socket = std::make_shared(); + ret = socket->open(subscription.signal_->get_message()->get_bus_device_name(),rx,tx); + subscription.socket_ = socket; + } + else if(!bus_name.empty()) + { + std::shared_ptr socket = std::make_shared(); + 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 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 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(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 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); 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 sig); static int create_rx_filter_can(low_can_subscription_t &subscription, std::shared_ptr sig); static int create_rx_filter_j1939(low_can_subscription_t &subscription, std::shared_ptr sig); + static int create_rx_filter_isotp(low_can_subscription_t &subscription, std::shared_ptr 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); }; -- cgit 1.2.3-korg