diff options
author | Romain Forlot <romain.forlot@iot.bzh> | 2019-11-26 16:19:38 +0100 |
---|---|---|
committer | Romain Forlot <romain.forlot@iot.bzh> | 2019-11-28 16:11:47 +0100 |
commit | 22b1864b72c2520fbc9d4e3d3332c28916b5a9ed (patch) | |
tree | 0d325c2a86751fe88ed046b448b783beec3cabbd /low-can-binding/binding | |
parent | fee3b49099fb39731e15f9e26ad5a873bc109f59 (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
Bug-AGL: SPEC-2976
Change-Id: Ic222615b547f28e926930e6c1dea2c0265055afd
Signed-off-by: Arthur Guyader <arthur.guyader@iot.bzh>
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
Diffstat (limited to 'low-can-binding/binding')
-rw-r--r-- | low-can-binding/binding/application-generated.cpp | 182 | ||||
-rw-r--r-- | low-can-binding/binding/low-can-cb.cpp | 116 | ||||
-rw-r--r-- | low-can-binding/binding/low-can-subscription.cpp | 114 | ||||
-rw-r--r-- | low-can-binding/binding/low-can-subscription.hpp | 13 |
4 files changed, 382 insertions, 43 deletions
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); }; |