CAN FD implementation 49/18749/3
authorRomain Forlot <romain.forlot@iot.bzh>
Fri, 28 Sep 2018 15:12:18 +0000 (17:12 +0200)
committerRomain Forlot <romain.forlot@iot.bzh>
Fri, 14 Dec 2018 08:58:56 +0000 (08:58 +0000)
Add a flag to CAN message definitions which set the message as using FD
protocol if true.

Use a new generated file with the new FD flag field on the message
definitions.

Change BCM socket "struct" using an union to store the CAN frames either
using the FD struct or the classic non FD struct. A BCM socket can only
one frame type once configured.

Use as much as possible the "struct canfd_frame" in the binding and only
make a difference before writing or reading the socket. From a memory
point of view both struct are identical and only the last member differ
and could hold more data with messages of 64 bytes long. So the
canfd_frame is compatible with the can_frame and can be differentiated
by a flag set in the can_id member.

Remove now unused code processing can_frame.

Keep the diagnostic manager using the classic CAN frame.

Set the maximum number of frames that a BCM socket can handle to 257.

Bug-AGL: SPEC-1980

Change-Id: Ifcc041281ea6745fc25cbd384743761f4446f489
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
13 files changed:
low-can-binding/binding/application-generated.cpp
low-can-binding/binding/low-can-cb.cpp
low-can-binding/binding/low-can-socket.cpp
low-can-binding/binding/low-can-socket.hpp
low-can-binding/can/can-encoder.cpp
low-can-binding/can/can-encoder.hpp
low-can-binding/can/can-message-definition.cpp
low-can-binding/can/can-message-definition.hpp
low-can-binding/can/can-message.cpp
low-can-binding/can/can-message.hpp
low-can-binding/diagnostic/diagnostic-manager.cpp
low-can-binding/utils/socketcan-bcm.cpp
low-can-binding/utils/socketcan-bcm.hpp

index 5a67d86..1b0a350 100644 (file)
@@ -7,7 +7,13 @@ application_t::application_t()
        , can_message_set_{
                {std::make_shared<can_message_set_t>(can_message_set_t{0,"AGL Virtual Car",
                        { // beginning can_message_definition_ vector
-                               {std::make_shared<can_message_definition_t>(can_message_definition_t{"ls",0x30,can_message_format_t::STANDARD,frequency_clock_t(5.00000f),true,
+                               {std::make_shared<can_message_definition_t>(can_message_definition_t{
+                                "ls",
+                                0x30,
+                                false,
+                                can_message_format_t::EXTENDED,
+                                frequency_clock_t(5.00000f),
+                                true,
                                        { // beginning can_signals vector
                                                {std::make_shared<can_signal_t> (can_signal_t{
                                                        "hvac.fan.speed",
@@ -83,7 +89,13 @@ application_t::application_t()
                                                })}
                                        } // end can_signals vector
                                })} // end can_message_definition entry
-,                              {std::make_shared<can_message_definition_t>(can_message_definition_t{"hs",0x3D9,can_message_format_t::STANDARD,frequency_clock_t(5.00000f),true,
+,                              {std::make_shared<can_message_definition_t>(can_message_definition_t{
+                                "hs",
+                                0x3D9,
+                                true,
+                                can_message_format_t::STANDARD,
+                                frequency_clock_t(5.00000f),
+                                true,
                                        { // beginning can_signals vector
                                                {std::make_shared<can_signal_t> (can_signal_t{
                                                        "engine.speed",
@@ -141,7 +153,13 @@ application_t::application_t()
                                                })}
                                        } // end can_signals vector
                                })} // end can_message_definition entry
-,                              {std::make_shared<can_message_definition_t>(can_message_definition_t{"hs",0x3E9,can_message_format_t::STANDARD,frequency_clock_t(5.00000f),true,
+,                              {std::make_shared<can_message_definition_t>(can_message_definition_t{
+                                "hs",
+                                0x3E9,
+                                false,
+                                can_message_format_t::EXTENDED,
+                                frequency_clock_t(5.00000f),
+                                true,
                                        { // beginning can_signals vector
                                                {std::make_shared<can_signal_t> (can_signal_t{
                                                        "vehicle.average.speed",
@@ -163,7 +181,13 @@ application_t::application_t()
                                                })}
                                        } // end can_signals vector
                                })} // end can_message_definition entry
-,                              {std::make_shared<can_message_definition_t>(can_message_definition_t{"hs",0x4D1,can_message_format_t::STANDARD,frequency_clock_t(5.00000f),true,
+,                              {std::make_shared<can_message_definition_t>(can_message_definition_t{
+                                "hs",
+                                0x4D1,
+                                false,
+                                can_message_format_t::STANDARD,
+                                frequency_clock_t(5.00000f),
+                                true,
                                        { // beginning can_signals vector
                                                {std::make_shared<can_signal_t> (can_signal_t{
                                                        "engine.oil.temp",
@@ -203,7 +227,13 @@ application_t::application_t()
                                                })}
                                        } // end can_signals vector
                                })} // end can_message_definition entry
-,                              {std::make_shared<can_message_definition_t>(can_message_definition_t{"hs",0x620,can_message_format_t::STANDARD,frequency_clock_t(5.00000f),true,
+,                              {std::make_shared<can_message_definition_t>(can_message_definition_t{
+                                "hs",
+                                0x620,
+                                false,
+                                can_message_format_t::STANDARD,
+                                frequency_clock_t(5.00000f),
+                                true,
                                        { // beginning can_signals vector
                                                {std::make_shared<can_signal_t> (can_signal_t{
                                                        "doors.boot.open",
@@ -297,7 +327,13 @@ application_t::application_t()
                                                })}
                                        } // end can_signals vector
                                })} // end can_message_definition entry
-,                              {std::make_shared<can_message_definition_t>(can_message_definition_t{"hs",0x799,can_message_format_t::STANDARD,frequency_clock_t(5.00000f),true,
+,                              {std::make_shared<can_message_definition_t>(can_message_definition_t{
+                                "hs",
+                                0x799,
+                                false,
+                                can_message_format_t::STANDARD,
+                                frequency_clock_t(5.00000f),
+                                true,
                                        { // beginning can_signals vector
                                                {std::make_shared<can_signal_t> (can_signal_t{
                                                        "windows.front_left.open",
index 3cb61c6..098f071 100644 (file)
@@ -407,7 +407,7 @@ void unsubscribe(afb_req_t request)
        do_subscribe_unsubscribe(request, false);
 }
 
-static int send_frame(const std::string& bus_name, const struct can_frame& cf)
+static int send_frame(struct canfd_frame& cfd, const std::string& bus_name)
 {
        if(bus_name.empty()) {
                return -1;
@@ -418,57 +418,54 @@ static int send_frame(const std::string& bus_name, const struct can_frame& cf)
        if( cd.count(bus_name) == 0)
                {cd[bus_name] = std::make_shared<low_can_socket_t>(low_can_socket_t());}
 
-       return cd[bus_name]->tx_send(cf, bus_name);
+       return cd[bus_name]->tx_send(cfd, bus_name);
 }
 
 static void write_raw_frame(afb_req_t request, const std::string& bus_name, json_object *json_value)
 {
-       struct can_frame cf;
-       struct json_object *json_can_data = nullptr;
+       struct canfd_frame cfd;
+       struct json_object *can_data = nullptr;
 
-       ::memset(&cf, 0, sizeof(cf));
+       ::memset(&cfd, 0, sizeof(cfd));
 
-       if(! wrap_json_unpack(json_value, "{sF, sF, so !}",
-                             "can_id", &cf.can_id,
-                             "can_dlc", &cf.can_dlc,
-                             "can_data", &json_can_data))
+       if(wrap_json_unpack(json_value, "{si, si, so !}",
+                             "can_id", &cfd.can_id,
+                             "can_dlc", &cfd.len,
+                             "can_data", &can_data))
        {
-               struct json_object *one_can_data;
-               size_t n = json_object_array_length(json_can_data);
+               afb_req_fail(request, "Invalid", "Frame object malformed");
+               return;
+       }
 
-               if(n <= 8 && n > 0)
-               {
-                       for (int i = 0 ; i < n ; i++)
-                       {
-                               one_can_data = json_object_array_get_idx(json_can_data, i);
-                               cf.data[i] = json_object_get_type(one_can_data) == json_type_int ? (uint8_t)json_object_get_int(one_can_data) : 0;
-                       }
-               }
-               else
+       if(cfd.len <= 8 && cfd.len > 0)
+       {
+               for (int i = 0 ; i < cfd.len ; i++)
                {
-                       afb_req_fail(request, "Error", "Data array must hold 1 to 8 values.");
-                       return;
+                       struct json_object *one_can_data = json_object_array_get_idx(can_data, i);
+                       cfd.data[i] = (json_object_is_type(one_can_data, json_type_int)) ?
+                                       (uint8_t)json_object_get_int(one_can_data) : 0;
                }
-
-               if(! send_frame(application_t::instance().get_can_bus_manager().get_can_device_name(bus_name), cf))
-                       afb_req_success(request, nullptr, "Message correctly sent");
-               else
-                       afb_req_fail(request, "Error", "sending the message. See the log for more details.");
-
+       }
+       else
+       {
+               afb_req_fail(request, "Invalid", "Data array must hold 1 to 8 values.");
                return;
        }
 
-       afb_req_fail(request, "Error", "Frame object malformed (must be \n \"frame\": {\"can_id\": int, \"can_dlc\": int, \"can_data\": [ int, int , int, int ,int , int ,int ,int]}");
+       if(! send_frame(cfd, application_t::instance().get_can_bus_manager().get_can_device_name(bus_name)))
+               afb_req_success(request, nullptr, "Message correctly sent");
+       else
+               afb_req_fail(request, "Error", "sending the message. See the log for more details.");
 }
 
 static void write_signal(afb_req_t request, const std::string& name, json_object *json_value)
 {
-       struct can_frame cf;
+       struct canfd_frame cfd;
        struct utils::signals_found sf;
        signal_encoder encoder = nullptr;
        bool send = true;
 
-       ::memset(&cf, 0, sizeof(cf));
+       ::memset(&cfd, 0, sizeof(cfd));
 
        openxc_DynamicField search_key = build_DynamicField(name);
        sf = utils::signals_manager_t::instance().find_signals(search_key);
@@ -491,8 +488,8 @@ static void write_signal(afb_req_t request, const std::string& name, json_object
                        encoder(*sig, dynafield_value, &send) :
                        encoder_t::encode_DynamicField(*sig, dynafield_value, &send);
 
-       if(! send_frame(sig->get_message()->get_bus_device_name(), encoder_t::build_frame(sig, value)) &&
-               send)
+       cfd = encoder_t::build_frame(sig, value);
+       if(! send_frame(cfd, sig->get_message()->get_bus_device_name()) && send)
                afb_req_success(request, nullptr, "Message correctly sent");
        else
                afb_req_fail(request, "Error", "Sending the message. See the log for more details.");
index db9b164..cd827b6 100644 (file)
@@ -185,11 +185,11 @@ int low_can_socket_t::open_socket(const std::string& bus_name)
 
 /// @brief Builds a BCM message head but doesn't set can_frame.
 ///
-/// @returns a simple_bcm_msg with the msg_head parts set and can_frame
+/// @returns a bcm_msg with the msg_head parts set and can_frame
 /// zeroed.
-struct utils::simple_bcm_msg low_can_socket_t::make_bcm_head(uint32_t opcode, uint32_t can_id, uint32_t flags, const struct timeval& timeout, const struct timeval& frequency_thinning) const
+struct utils::bcm_msg low_can_socket_t::make_bcm_head(uint32_t opcode, uint32_t can_id, uint32_t flags, const struct timeval& timeout, const struct timeval& frequency_thinning) const
 {
-       struct utils::simple_bcm_msg bcm_msg;
+       struct utils::bcm_msg bcm_msg;
        ::memset(&bcm_msg, 0, sizeof(bcm_msg));
 
        bcm_msg.msg_head.opcode  = opcode;
@@ -203,13 +203,23 @@ struct utils::simple_bcm_msg low_can_socket_t::make_bcm_head(uint32_t opcode, ui
        return bcm_msg;
 }
 
-/// @brief Take an existing simple_bcm_msg struct and add a can_frame.
+/// @brief Take an existing bcm_msg struct and add a can_frame.
 /// Currently only 1 uniq can_frame can be added, it's not possible to build
 /// a multiplexed message with several can_frame.
-void low_can_socket_t::add_bcm_frame(const struct can_frame& cf, struct utils::simple_bcm_msg& bcm_msg) const
+void low_can_socket_t::add_one_bcm_frame(struct canfd_frame& cfd, struct utils::bcm_msg& bcm_msg) const
 {
+       struct can_frame cf;
+
+       if (bcm_msg.msg_head.flags & CAN_FD_FRAME)
+               bcm_msg.fd_frames[bcm_msg.msg_head.nframes] = cfd;
+       else
+       {
+               cf.can_id = cfd.can_id;
+               cf.can_dlc = cfd.len;
+               ::memcpy(&cf.data, cfd.data, cfd.len);
+               bcm_msg.frames[bcm_msg.msg_head.nframes] = cf;
+       }
        bcm_msg.msg_head.nframes++;
-       bcm_msg.frames = cf;
 }
 
 /// @brief Create a RX_SETUP receive job to be used by the BCM socket for a CAN signal
@@ -218,26 +228,37 @@ void low_can_socket_t::add_bcm_frame(const struct can_frame& cf, struct utils::s
 /// @return 0 if ok else -1
 int low_can_socket_t::create_rx_filter(std::shared_ptr<can_signal_t> sig)
 {
+       uint32_t flags;
+       float val;
+       struct timeval freq, timeout = {0, 0};
+       struct canfd_frame cfd;
        can_signal_= sig;
 
-       struct can_frame cfd;
-       memset(&cfd, 0, sizeof(cfd));
-
-       float val = (float)(1 << can_signal_->get_bit_size()) - 1;
-       bitfield_encode_float(val,
-                                                       can_signal_->get_bit_position(),
-                                                       can_signal_->get_bit_size(),
-                                                       can_signal_->get_factor(),
-                                                       can_signal_->get_offset(),
-                                                       cfd.data,
-                                                       CAN_MAX_DLEN);
+       if (sig->get_message()->is_fd())
+       {
+               flags = SETTIMER|RX_NO_AUTOTIMER|CAN_FD_FRAME;
+               cfd.len = CANFD_MAX_DLEN;
+       }
+       else
+       {
+               flags = SETTIMER|RX_NO_AUTOTIMER;
+               cfd.len = CAN_MAX_DLEN;
+       }
+       val = (float)(1 << can_signal_->get_bit_size()) - 1;
+       if(! bitfield_encode_float(val,
+                                  can_signal_->get_bit_position(),
+                                  can_signal_->get_bit_size(),
+                                  1,
+                                  can_signal_->get_offset(),
+                                  cfd.data,
+                                  cfd.len))
+               return -1;
 
-       struct timeval freq, timeout = {0, 0};
        frequency_clock_t f = event_filter_.frequency == 0 ? can_signal_->get_frequency() : frequency_clock_t(event_filter_.frequency);
        freq = f.get_timeval_from_period();
 
-       utils::simple_bcm_msg bcm_msg = make_bcm_head(RX_SETUP, can_signal_->get_message()->get_id(), SETTIMER|RX_NO_AUTOTIMER, timeout, freq);
-       add_bcm_frame(cfd, bcm_msg);
+       utils::bcm_msg bcm_msg = make_bcm_head(RX_SETUP, can_signal_->get_message()->get_id(), flags, timeout, freq);
+       add_one_bcm_frame(cfd, bcm_msg);
 
        return create_rx_filter(bcm_msg);
 }
@@ -254,19 +275,19 @@ int low_can_socket_t::create_rx_filter(std::shared_ptr<diagnostic_message_t> sig
        //struct timeval timeout = frequency_clock_t(10).get_timeval_from_period();
        struct timeval timeout = {0,0};
 
-       utils::simple_bcm_msg bcm_msg =  make_bcm_head(RX_SETUP, OBD2_FUNCTIONAL_BROADCAST_ID, SETTIMER|RX_NO_AUTOTIMER|RX_FILTER_ID, timeout, freq);
+       utils::bcm_msg bcm_msg =  make_bcm_head(RX_SETUP, OBD2_FUNCTIONAL_BROADCAST_ID, SETTIMER|RX_NO_AUTOTIMER|RX_FILTER_ID, timeout, freq);
        return create_rx_filter(bcm_msg);
 }
 
 /// @brief Create a RX_SETUP receive job used by the BCM socket directly from
-/// a simple_bcm_msg. The method should not be used directly but rather through the
+/// a bcm_msg. The method should not be used directly but rather through the
 /// two previous method with can_signal_t or diagnostic_message_t object.
 ///
 /// If the CAN arbitration ID is the OBD2 functional broadcast id the subscribed
 /// to the 8 classics OBD2 functional response ID
 ///
 /// @return 0 if ok else -1
-int low_can_socket_t::create_rx_filter(utils::simple_bcm_msg& bcm_msg)
+int low_can_socket_t::create_rx_filter(utils::bcm_msg& bcm_msg)
 {
        // Make sure that socket is opened.
        if(open_socket() < 0)
@@ -299,12 +320,10 @@ int low_can_socket_t::create_rx_filter(utils::simple_bcm_msg& bcm_msg)
 /// send a message
 ///
 /// @return 0 if ok else -1
-int low_can_socket_t::tx_send(const struct can_frame& cf, const std::string& bus_name)
+int low_can_socket_t::tx_send(struct canfd_frame& cfd, const std::string& bus_name)
 {
-       can_signal_ = nullptr;
-
-       utils::simple_bcm_msg bcm_msg =  make_bcm_head(TX_SEND);
-       add_bcm_frame(cf, bcm_msg);
+       utils::bcm_msg bcm_msg =  make_bcm_head(TX_SEND, cfd.can_id);
+       add_one_bcm_frame(cfd, bcm_msg);
 
        if(open_socket(bus_name) < 0)
                {return -1;}
index 48ed47f..d46f1f8 100644 (file)
@@ -25,6 +25,8 @@
 #include "../diagnostic/diagnostic-message.hpp"
 #include "../utils/socketcan-bcm.hpp"
 
+#define OBDII_MAX_SIMULTANEOUS_RESPONSES 8
+
 /// @brief Filtering values. Theses values have to be tested in
 /// can_bus_t::apply_filter method.
 struct event_filter_t
@@ -81,14 +83,14 @@ public:
        void set_min(float min);
        void set_max(float max);
 
-       struct utils::simple_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}) const;
-       void add_bcm_frame(const struct can_frame& cfd, struct utils::simple_bcm_msg& bcm_msg) const;
+       struct utils::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}) const;
+       void add_one_bcm_frame(struct canfd_frame& cfd, struct utils::bcm_msg& bcm_msg) const;
 
        int open_socket(const std::string& bus_name = "");
 
        int create_rx_filter(std::shared_ptr<can_signal_t> sig);
        int create_rx_filter(std::shared_ptr<diagnostic_message_t> sig);
-       int create_rx_filter(utils::simple_bcm_msg& bcm_msg);
+       int create_rx_filter(utils::bcm_msg& bcm_msg);
 
-       int tx_send(const struct can_frame& cf, const std::string& bus_name);
+       int tx_send(struct canfd_frame& cfd, const std::string& bus_name);
 };
index 4f1efa2..4b8a296 100644 (file)
 /// @param[out] data - The destination buffer.
 /// @param[in] length - The length of the destination buffer.
 ///
-/// @return Returns a can_frame struct initialized and ready to be send.
-const can_frame encoder_t::build_frame(const std::shared_ptr<can_signal_t>& signal, uint64_t value)
+/// @return Returns a canfd_frame struct initialized and ready to be send.
+const canfd_frame encoder_t::build_frame(const std::shared_ptr<can_signal_t>& signal, uint64_t value)
 {
-       struct can_frame cf;
+       struct canfd_frame cf;
        ::memset(&cf, 0, sizeof(cf));
 
        cf.can_id = signal->get_message()->get_id();
-       cf.can_dlc = CAN_MAX_DLEN;
+       cf.len = signal->get_message()->is_fd() ?
+                CANFD_MAX_DLEN : CAN_MAX_DLEN;
 
        signal->set_last_value((float)value);
 
@@ -48,7 +49,7 @@ const can_frame encoder_t::build_frame(const std::shared_ptr<can_signal_t>& sign
                                        sig->get_factor(),
                                        sig->get_offset(),
                                        cf.data,
-                                       CAN_MAX_DLEN);
+                                       cf.len);
        }
 
        return cf;
index c79e224..f839883 100644 (file)
@@ -24,7 +24,7 @@
 class encoder_t
 {
 public:
-       static const can_frame build_frame(const std::shared_ptr<can_signal_t>& signal, uint64_t value);
+       static const canfd_frame build_frame(const std::shared_ptr<can_signal_t>& signal, uint64_t value);
        static uint64_t encode_state(const can_signal_t& signal, const std::string& value, bool* send);
        static uint64_t encode_boolean(const can_signal_t& signal, bool value, bool* send);
        static uint64_t encode_number(const can_signal_t& signal, float value, bool* send);
index 28d45fe..ae957d1 100644 (file)
@@ -54,6 +54,7 @@ can_message_definition_t::can_message_definition_t(
 can_message_definition_t::can_message_definition_t(
        const std::string bus,
        uint32_t id,
+       bool is_fd,
        can_message_format_t format,
        frequency_clock_t frequency_clock,
        bool force_send_changed,
@@ -61,6 +62,7 @@ can_message_definition_t::can_message_definition_t(
        :  parent_{nullptr},
        bus_{bus},
        id_{id},
+       is_fd_(is_fd),
        format_{format},
        frequency_clock_{frequency_clock},
        force_send_changed_{force_send_changed},
@@ -84,6 +86,11 @@ uint32_t can_message_definition_t::get_id() const
        return id_;
 }
 
+bool can_message_definition_t::is_fd() const
+{
+       return is_fd_;
+}
+
 std::vector<std::shared_ptr<can_signal_t> >& can_message_definition_t::get_can_signals()
 {
        return can_signals_;
index 6d0f17d..b9025cb 100644 (file)
@@ -43,6 +43,7 @@ private:
        can_message_set_t* parent_; ///< parent_ - Pointer to the CAN message set holding this CAN message definition */
        std::string bus_; ///< bus_ - Address of CAN bus device. */
        uint32_t id_; ///< id_ - The ID of the message.*/
+       bool is_fd_; /*!< uses_fd_ - Flags to enable an FD CAN message communication*/
        can_message_format_t format_; ///< format_ - the format of the message's ID.*/
        frequency_clock_t frequency_clock_; ///<  clock_ - an optional frequency clock to control the output of this
                                                        ///      message, if sent raw, or simply to mark the max frequency for custom
@@ -59,11 +60,18 @@ public:
        can_message_definition_t(const std::string bus);
        can_message_definition_t(const std::string bus, uint32_t id, frequency_clock_t frequency_clock, bool force_send_changed);
        can_message_definition_t(const std::string bus, uint32_t id, can_message_format_t format, frequency_clock_t frequency_clock, bool force_send_changed);
-       can_message_definition_t(const std::string bus, uint32_t id, can_message_format_t format, frequency_clock_t frequency_clock, bool force_send_changed, const std::vector<std::shared_ptr<can_signal_t> >& can_signals);
+       can_message_definition_t(const std::string bus,
+                                uint32_t id,
+                                bool is_fd,
+                                can_message_format_t format,
+                                frequency_clock_t frequency_clock,
+                                bool force_send_changed,
+                                const std::vector<std::shared_ptr<can_signal_t> >& can_signals);
 
        const std::string get_bus_name() const;
        const std::string get_bus_device_name() const;
        uint32_t get_id() const;
+       bool is_fd() const;
        std::vector<std::shared_ptr<can_signal_t> >& get_can_signals();
 
        void set_parent(can_message_set_t* parent);
index 1b27d0f..9ec3566 100644 (file)
@@ -266,124 +266,3 @@ can_message_t can_message_t::convert_from_frame(const struct canfd_frame& frame,
 
        return can_message_t(maxdlen, id, length, format, rtr_flag, flags, data, timestamp);
 }
-
-/// @brief Take a can_frame struct to initialize class members
-///
-/// This is the preferred way to initialize class members.
-///
-/// @param[in] frame - can_frame to convert coming from a read of CAN socket
-/// @param[in] nbytes - bytes read from socket read operation.
-///
-/// @return A can_message_t object fully initialized with can_frame values.
-can_message_t can_message_t::convert_from_frame(const struct can_frame& frame, size_t nbytes, uint64_t timestamp)
-{
-       uint8_t maxdlen = 0, length = 0, flags = 0;
-       uint32_t id;
-       can_message_format_t format;
-       bool rtr_flag;
-       std::vector<uint8_t> data;
-
-       if(nbytes <= CAN_MTU)
-       {
-                       AFB_DEBUG("Got a legacy CAN frame");
-                       maxdlen = CAN_MAX_DLEN;
-       }
-       else
-       {
-                       AFB_ERROR("unsupported CAN frame");
-       }
-
-       if (frame.can_id & CAN_ERR_FLAG)
-       {
-               format = can_message_format_t::INVALID;
-               id = frame.can_id & (CAN_ERR_MASK|CAN_ERR_FLAG);
-       }
-       else if (frame.can_id & CAN_EFF_FLAG)
-       {
-               format = can_message_format_t::EXTENDED;
-               id = frame.can_id & CAN_EFF_MASK;
-       }
-       else
-       {
-               format = can_message_format_t::STANDARD;
-               id = frame.can_id & CAN_SFF_MASK;
-       }
-
-       /* Overwrite length_ if RTR flags is detected.
-        * standard CAN frames may have RTR enabled. There are no ERR frames with RTR */
-       if (frame.can_id & CAN_RTR_FLAG)
-       {
-               rtr_flag = true;
-               if(frame.can_dlc && frame.can_dlc <= CAN_MAX_DLC)
-               {
-                       if(rtr_flag)
-                               length = frame.can_dlc& 0xF;
-                       else
-                       {
-                               length = (frame.can_dlc > maxdlen) ? maxdlen : frame.can_dlc;
-                       }
-               }
-       }
-       else
-       {
-               length = (frame.can_dlc > maxdlen) ? maxdlen : frame.can_dlc;
-
-               if (data.capacity() < maxdlen)
-                       data.reserve(maxdlen);
-                               int i;
-
-                       data.clear();
-                       /* maxdlen_ is now set at CAN_MAX_DLEN or CANFD_MAX_DLEN, respectively 8 and 64 bytes*/
-                       for(i=0;i<maxdlen;i++)
-                       {
-                               data.push_back(frame.data[i]);
-                       };
-
-//             AFB_DEBUG("Found id: %X, format: %X, length: %X, data %02X%02X%02X%02X%02X%02X%02X%02X",
-//                                                             id, (uint8_t)format, length, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
-       }
-
-       return can_message_t(maxdlen, id, length, format, rtr_flag, flags, data, timestamp);
-}
-
-/// @brief Take all initialized class members and build a
-/// canfd_frame struct that can be use to send a CAN message over
-/// the bus.
-///
-/// @return canfd_frame struct built from class members.
-struct canfd_frame can_message_t::convert_to_canfd_frame()
-{
-       canfd_frame frame;
-
-       if(is_correct_to_send())
-       {
-               frame.can_id = get_id();
-               frame.len = get_length();
-               ::memcpy(frame.data, get_data(), length_);
-       }
-       else
-               AFB_ERROR("can_message_t not correctly initialized to be sent");
-
-       return frame;
-}
-
-/// @brief Take all initialized class members and build a
-/// can_frame struct that can be use to send a CAN message over
-/// the bus.
-///
-/// @return can_frame struct built from class members.
-struct can_frame can_message_t::convert_to_can_frame()
-{
-       can_frame frame;
-
-       if(is_correct_to_send())
-       {
-               frame.can_id = get_id();
-               frame.can_dlc = get_length();
-               ::memcpy(frame.data, get_data(), length_);
-       }
-       else
-               AFB_ERROR("can_message_t not correctly initialized to be sent");
-
-       return frame;
-}
index b206ebd..cf960b9 100644 (file)
@@ -73,8 +73,4 @@ public:
        bool is_correct_to_send();
 
        static can_message_t convert_from_frame(const canfd_frame& frame, size_t nbytes, uint64_t timestamp);
-       static can_message_t convert_from_frame(const can_frame& frame, size_t nbytes, uint64_t timestamp);
-
-       struct canfd_frame convert_to_canfd_frame();
-       struct can_frame convert_to_can_frame();
 };
index bc335df..8932f25 100644 (file)
@@ -102,27 +102,26 @@ bool diagnostic_manager_t::shims_send(const uint32_t arbitration_id, const uint8
 
        // Make sure that socket has been opened.
        if(! tx_socket)
-               tx_socket.open(
-                       dm.get_bus_device_name());
+               tx_socket.open(dm.get_bus_device_name());
 
-       struct utils::simple_bcm_msg bcm_msg;
-       struct can_frame cfd;
-
-       memset(&cfd, 0, sizeof(cfd));
-       memset(&bcm_msg.msg_head, 0, sizeof(bcm_msg.msg_head));
+       struct utils::bcm_msg bcm_msg;
+       struct can_frame cf;
 
        struct timeval freq = current_adr->get_frequency_clock().get_timeval_from_period();
 
        bcm_msg.msg_head.opcode  = TX_SETUP;
        bcm_msg.msg_head.can_id  = arbitration_id;
        bcm_msg.msg_head.flags = SETTIMER|STARTTIMER|TX_CP_CAN_ID;
+       bcm_msg.msg_head.count = 0;
        bcm_msg.msg_head.ival2.tv_sec = freq.tv_sec;
        bcm_msg.msg_head.ival2.tv_usec = freq.tv_usec;
        bcm_msg.msg_head.nframes = 1;
-       cfd.can_dlc = size;
-       ::memcpy(cfd.data, data, size);
+       cf.can_dlc = size;
+
+       ::memset(cf.data, 0, sizeof(cf.data));
+       ::memcpy(cf.data, data, size);
 
-       bcm_msg.frames = cfd;
+       bcm_msg.frames[0] = cf;
 
        tx_socket << bcm_msg;
        if(tx_socket)
index 750e772..d1fd8e0 100644 (file)
@@ -72,7 +72,7 @@ namespace utils
        /// then CAN message will be zeroed and must be handled later.
        socketcan_bcm_t& operator>>(socketcan_bcm_t& s, can_message_t& cm)
        {
-               struct utils::simple_bcm_msg msg;
+               struct utils::bcm_msg msg;
 
                ::memset(&msg, 0, sizeof(msg));
                const struct sockaddr_can& addr = s.get_tx_address();
@@ -85,17 +85,30 @@ namespace utils
                long unsigned int frame_size = nbytes-sizeof(struct bcm_msg_head);
 
                AFB_DEBUG("Data available: %li bytes read. BCM head, opcode: %i, can_id: %i, nframes: %i", frame_size, msg.msg_head.opcode, msg.msg_head.can_id, msg.msg_head.nframes);
-               AFB_DEBUG("read: Found on bus %s:\n id: %X, length: %X, data %02X%02X%02X%02X%02X%02X%02X%02X", ifr.ifr_name, msg.msg_head.can_id, msg.frames.can_dlc,
-                       msg.frames.data[0], msg.frames.data[1], msg.frames.data[2], msg.frames.data[3], msg.frames.data[4], msg.frames.data[5], msg.frames.data[6], msg.frames.data[7]);
 
                struct timeval tv;
                ioctl(s.socket(), SIOCGSTAMP, &tv);
                uint64_t timestamp = 1000000 * tv.tv_sec + tv.tv_usec;
-               cm = ::can_message_t::convert_from_frame(msg.frames ,
-                               frame_size,
-                               timestamp);
+               cm = can_message_t::convert_from_frame(msg.fd_frames[0] , frame_size, timestamp);
                cm.set_sub_id((int)s.socket());
 
                return s;
        }
+
+       socketcan_bcm_t& operator<<(socketcan_bcm_t& s, const std::vector<struct utils::bcm_msg>& vobj)
+       {
+               for(const auto& obj : vobj)
+                       s << obj;
+               return s;
+       }
+
+       socketcan_bcm_t& operator<<(socketcan_bcm_t& s, const struct utils::bcm_msg& obj)
+       {
+               size_t size = (obj.msg_head.flags & CAN_FD_FRAME) ?
+                             (size_t)((char*)&obj.fd_frames[obj.msg_head.nframes] - (char*)&obj):
+                             (size_t)((char*)&obj.frames[obj.msg_head.nframes] - (char*)&obj);
+               if (::sendto(s.socket(), &obj, size, 0, (const struct sockaddr*)&s.get_tx_address(), sizeof(s.get_tx_address())) < 0)
+                       AFB_API_ERROR(afbBindingV3root, "Error sending : %i %s", errno, ::strerror(errno));
+               return s;
+       }
 }
index 22927cb..478a529 100644 (file)
 #include "socketcan.hpp"
 #include "../can/can-message.hpp"
 
+#define MAX_BCM_CAN_FRAMES 257
+
 namespace utils
 {
-       struct simple_bcm_msg
-       {
-               struct bcm_msg_head msg_head;
-               struct can_frame frames;
-       };
-
-#ifdef KERNEL_MINIMAL_VERSION_OK
-       struct canfd_bcm_msg
+       struct bcm_msg
        {
                struct bcm_msg_head msg_head;
-               struct canfd_frame frames;
-               canfd_bcm_msg() { msg_head.flags |= CAN_FD_FRAME; }
+               union {
+                       struct canfd_frame fd_frames[MAX_BCM_CAN_FRAMES];
+                       struct can_frame frames[MAX_BCM_CAN_FRAMES];
+               };
        };
-#endif
 
-       /// @brief derivated socketcan class specialized for BCM CAN socket.
+       /// @brief derivated socketcan class specialized for BCM CAN socket.make_bcm_head
        class socketcan_bcm_t : public socketcan_t
        {
        public:
@@ -50,6 +46,7 @@ namespace utils
        };
 
        socketcan_bcm_t& operator>>(socketcan_bcm_t& s, can_message_t& cm);
-//     socketcan_bcm_t& operator<<(socketcan_bcm_t& s, const struct simple_bcm_msg& obj);
-//     socketcan_bcm_t& operator<<(socketcan_bcm_t& s, const struct canfd_bcm_msg& obj);
+
+       socketcan_bcm_t& operator<<(socketcan_bcm_t& s, const std::vector<struct bcm_msg>& obj);
+       socketcan_bcm_t& operator<<(socketcan_bcm_t& s, const struct bcm_msg& obj);
 }