diff options
-rw-r--r-- | docs/4-Installation-ISOTP.md | 50 | ||||
-rw-r--r-- | docs/5-Usage.md (renamed from docs/4-Usage.md) | 12 | ||||
-rw-r--r-- | docs/api-services-book.yml | 4 | ||||
-rw-r--r-- | low-can-binding/binding/low-can-cb.cpp | 1 | ||||
-rw-r--r-- | low-can-binding/binding/low-can-subscription.cpp | 125 | ||||
-rw-r--r-- | low-can-binding/binding/low-can-subscription.hpp | 4 | ||||
-rw-r--r-- | low-can-binding/utils/socketcan-j1939.cpp | 195 |
7 files changed, 191 insertions, 200 deletions
diff --git a/docs/4-Installation-ISOTP.md b/docs/4-Installation-ISOTP.md new file mode 100644 index 00000000..c8fc31f6 --- /dev/null +++ b/docs/4-Installation-ISOTP.md @@ -0,0 +1,50 @@ +# Installation isotp for AGL + +## Compilation and installation of module kernel isotp + +##### Clone repository Linux Kernel Module for ISO 15765-2:2016 CAN transport protocol + +```bash +git clone https://github.com/hartkopp/can-isotp.git +``` + +##### Move into the new repository + +```bash +cd can-isotp +``` + +##### Install packages to build + +```bash +sudo apt-get install build-essential linux-headers-$(uname -r) +``` + +##### Compile + +```bash +make +``` + +##### Install + +```bash +sudo make modules_install +``` + +##### Load module + + +```bash +modprobe can +modprobe vcan +sudo insmod ./net/can/can-isotp.ko +``` + + +## Include headers files + + +```bash +sudo cp include/uapi/linux/can/isotp.h /usr/include/linux/can/ +```
\ No newline at end of file diff --git a/docs/4-Usage.md b/docs/5-Usage.md index 6c6d1380..9e9841e8 100644 --- a/docs/4-Usage.md +++ b/docs/5-Usage.md @@ -306,6 +306,8 @@ argument filter with one or more of the filters available : the subscribed client(s). * max: Maximum value that the decoded value needs to be below to get pushed to the subscribed client(s) +* rx_id : For the ISO TP protocol, define the id of source to write a message +* tx_id : For the ISO TP protocol, define the id of emitter to receive message Order doesn't matter neither the number of filters chosen, you can use one, two or all of them at once. @@ -316,6 +318,8 @@ Usage examples : low-can subscribe {"event": "messages.engine.speed", "filter": { "frequency": 3, "min": 1250, "max": 3500}} low-can subscribe {"event": "messages.engine.load", "filter": { "min": 30, "max": 100}} low-can subscribe {"event": "messages.vehicle.speed", "filter": { "frequency": 2}} +# ISOTP +low-can subscribe {"id": 273, "filter": {"tx_id" : 562}} ``` ## Get last signal value and list of configured signals @@ -354,9 +358,13 @@ low-can write { "bus_name": "hs", "frame": { "can_id": 1568, "can_dlc": 8, "can_ # Write a signal's value. low-can write { "signal_name": "engine.speed", "signal_value": 1256} # Write J1939 'single frame' -low-can write { "bus_name": "j1939", "frame": { "pgn": 62420, "length":8, "data": [ 255,255,255,255,255,255,255,255]} } +low-can write { "bus_name": "j1939", "frame": { "pgn": 61442, "length":8, "data": [ 255,255,255,255,255,255,255,255]} } # Write J1939 'multi frame' -low-can write { "bus_name": "j1939", "frame": { "pgn": 62420, "length":9, "data": [ 255,255,255,255,255,255,255,255,254]} } +low-can write { "bus_name": "j1939", "frame": { "pgn": 61442, "length":9, "data": [ 255,255,255,255,255,255,255,255,254]} } +# Write ISOTP 'single frame' +low-can write {"bus_name": "hs", "filter": {"rx_id" : 562}, "frame": { "can_id": 273, "can_dlc": 8, "can_data": [ 255,255,255,255,255,255,255,255]} } +# Write ISOTP 'multi frame' +low-can write {"bus_name": "hs", "filter": {"rx_id" : 562}, "frame": { "can_id": 273, "can_dlc": 9, "can_data": [ 255,255,255,255,255,255,255,255,25]} } ``` To be able to use write capability, you need to add the permission diff --git a/docs/api-services-book.yml b/docs/api-services-book.yml index 225d67b8..f2909c3c 100644 --- a/docs/api-services-book.yml +++ b/docs/api-services-book.yml @@ -14,5 +14,7 @@ books: name: Installation Guide - url: 3-Installation-J1939.md name: Installation Guide for J1939 - - url: 4-Usage.md + - url: 4-Installation-ISOTP.md + name: Installation Guide for ISOTP + - url: 5-Usage.md name: Usage Guide diff --git a/low-can-binding/binding/low-can-cb.cpp b/low-can-binding/binding/low-can-cb.cpp index 5879b686..fd57867c 100644 --- a/low-can-binding/binding/low-can-cb.cpp +++ b/low-can-binding/binding/low-can-cb.cpp @@ -297,6 +297,7 @@ static int subscribe_unsubscribe_signals(afb_req_t request, /// @param[in] afb_req request : contains original request use to subscribe or unsubscribe /// @param[in] subscribe boolean value, which chooses between a subscription operation or an unsubscription /// @param[in] signals - struct containing vectors with signal_t and diagnostic_messages to subscribe +/// @param[in] event_filter - stuct containing filter on the signal /// /// @return Number of correctly subscribed signal /// diff --git a/low-can-binding/binding/low-can-subscription.cpp b/low-can-binding/binding/low-can-subscription.cpp index df5a8f4d..a472d997 100644 --- a/low-can-binding/binding/low-can-subscription.cpp +++ b/low-can-binding/binding/low-can-subscription.cpp @@ -124,21 +124,44 @@ int low_can_subscription_t::unsubscribe(afb_req_t request) return afb_req_unsubscribe(request, event_); } +/** + * @brief Getter of index of subscription + * + * @return int Index + */ int low_can_subscription_t::get_index() const { return index_; } +/** + * @brief Getter of signal of subscription + * + * @return const std::shared_ptr<signal_t> A shared pointer of the signal + */ const std::shared_ptr<signal_t> low_can_subscription_t::get_signal() const { return signal_; } +/** + * @brief Check if the signal and event are the same that the subscription + * + * @param signal the signal compared + * @param event_filter the event_filter compared + * @return true if they are equal + * @return false if they are not equal + */ bool low_can_subscription_t::is_signal_subscription_corresponding(const std::shared_ptr<signal_t> signal, const struct event_filter_t& event_filter) const { return signal_ == signal && event_filter_ == event_filter; } +/** + * @brief Getter for diagnostic messages of subscription + * + * @return const vector_ptr_diag_msg_t Vector of pointer of diagnostic message + */ const vect_ptr_diag_msg_t low_can_subscription_t::get_diagnostic_message() const { return diagnostic_message_; @@ -201,66 +224,131 @@ const std::string low_can_subscription_t::get_name(uint32_t pid) const return ""; } +/** + * @brief Getter of the frequency of the event_filter + * + * @return float The frequency + */ float low_can_subscription_t::get_frequency() const { return event_filter_.frequency; } +/** + * @brief Getter of the min of the event_filter + * + * @return float The min value filtered + */ float low_can_subscription_t::get_min() const { return event_filter_.min; } +/** + * @brief Getter of the max of the event_filter + * + * @return float The max value filtered + */ float low_can_subscription_t::get_max() const { return event_filter_.max; } +/** + * @brief Getter of the rx_id of the event_filter + * + * @return canid_t The rx_id value + */ canid_t low_can_subscription_t::get_rx_id() const { return event_filter_.rx_id; } +/** + * @brief Getter of the tx_id of the event_filter + * + * @return canid_t The tx_id value + */ canid_t low_can_subscription_t::get_tx_id() const { return event_filter_.tx_id; } +/** + * @brief Getter of the socket of the subscription + * + * @return std::shared_ptr<utils::socketcan_t> Pointer of the socket object + */ std::shared_ptr<utils::socketcan_t> low_can_subscription_t::get_socket() { return socket_; } +/** + * @brief Setter for the frequency of the event_filter + * + * @param freq The new frequency + */ void low_can_subscription_t::set_frequency(float freq) { event_filter_.frequency = freq; } +/** + * @brief Setter for the min of the event_filter + * + * @param min The new min + */ void low_can_subscription_t::set_min(float min) { event_filter_.min = min; } +/** + * @brief Setter for the max of the event_filter + * + * @param max The new max + */ void low_can_subscription_t::set_max(float max) { event_filter_.max = max; } +/** + * @brief Setter for the rx_id of the event_filter + * + * @param rx_id The new rx_id + */ void low_can_subscription_t::set_rx_id(canid_t rx_id) { event_filter_.rx_id = rx_id; } +/** + * @brief Setter for the tx_id of the event_filter + * + * @param tx_id The new tx_id + */ void low_can_subscription_t::set_tx_id(canid_t tx_id) { event_filter_.tx_id = tx_id; } +/** + * @brief Setter for the index of the subscription + * + * @param index The new index + */ void low_can_subscription_t::set_index(int index) { index_ = index; } +/** + * @brief Setter for the signal of the subscription + * + * @param signal The new signal + */ void low_can_subscription_t::set_signal(std::shared_ptr<signal_t> signal) { signal_ = signal; @@ -421,6 +509,13 @@ void low_can_subscription_t::remove_last_bcm_frame(struct bcm_msg& bcm_msg) } #ifdef USE_FEATURE_J1939 +/** + * @brief Create a j1939 socket to read message + * + * @param subscription The subscription + * @param sig The signal subscribed + * @return int 0 if ok else -1 + */ int low_can_subscription_t::create_rx_filter_j1939(low_can_subscription_t &subscription, std::shared_ptr<signal_t> sig) { subscription.signal_= sig; @@ -434,6 +529,13 @@ int low_can_subscription_t::create_rx_filter_j1939(low_can_subscription_t &subsc } #endif +/** + * @brief Create an iso tp socket to read message + * + * @param subscription The subscription + * @param sig The signal subscribed + * @return int 0 if ok else -1 + */ int low_can_subscription_t::create_rx_filter_isotp(low_can_subscription_t &subscription, std::shared_ptr<signal_t> sig) { subscription.signal_= sig; @@ -531,6 +633,13 @@ int low_can_subscription_t::create_rx_filter_can(low_can_subscription_t &subscri return create_rx_filter_bcm(subscription, bcm_msg); } +/** + * @brief Create the good socket to read message + * depending on the signal + * + * @param sig The signal subscribed + * @return 0 if ok else -1 + */ int low_can_subscription_t::create_rx_filter(std::shared_ptr<signal_t> sig) { if(!sig->get_message()->is_isotp() && !sig->get_message()->is_j1939()) @@ -666,6 +775,14 @@ int low_can_subscription_t::tx_send(low_can_subscription_t &subscription, messag } #ifdef USE_FEATURE_J1939 +/** + * @brief Allows to open socket j1939 and send j1939 messsage + * + * @param subscription The subscription + * @param message The j1939 message to send + * @param bus_name The bus name where to send message + * @return int 0 if ok else -1 + */ int low_can_subscription_t::j1939_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); @@ -689,6 +806,14 @@ int low_can_subscription_t::j1939_send(low_can_subscription_t &subscription, mes #endif +/** + * @brief Allows to open socket isotp and send can messsage + * + * @param subscription The subscription + * @param message The can message to send + * @param bus_name The bus name where to send message + * @return int 0 if ok else -1 + */ 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); diff --git a/low-can-binding/binding/low-can-subscription.hpp b/low-can-binding/binding/low-can-subscription.hpp index 5abf8550..ac08d265 100644 --- a/low-can-binding/binding/low-can-subscription.hpp +++ b/low-can-binding/binding/low-can-subscription.hpp @@ -35,8 +35,8 @@ 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; + canid_t rx_id; ///< rx_id - RX_ID for ISO_TP protocol + canid_t tx_id; ///< tx_id - TX_ID for ISO_TP protocol 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 { diff --git a/low-can-binding/utils/socketcan-j1939.cpp b/low-can-binding/utils/socketcan-j1939.cpp deleted file mode 100644 index a7938d61..00000000 --- a/low-can-binding/utils/socketcan-j1939.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2018, 2019 "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 <net/if.h> -#include <sys/ioctl.h> -#include <fcntl.h> -#include "./socketcan-j1939.hpp" -#include "../binding/application.hpp" - -namespace utils -{ - /// @brief Connect the socket. - /// @return 0 if success. - int socketcan_j1939_t::connect(const struct sockaddr* addr, socklen_t len) - { - return socket_ != INVALID_SOCKET ? ::connect(socket_, addr, len) : 0; - } - - /// @brief Bind the socket. - /// @return 0 if success. - int socketcan_j1939_t::bind(const struct sockaddr* addr, socklen_t len) - { - return socket_ != INVALID_SOCKET ? ::bind(socket_, addr, len) : 0; - } - - void socketcan_j1939_t::filter(name_t name, pgn_t pgn, uint8_t addr, uint64_t name_mask, uint32_t pgn_mask, uint8_t addr_mask) - { - int filter_on = 0; - struct j1939_filter filter; - memset(&filter, 0, sizeof(filter)); - if (name) - { - filter.name = name; - if(name_mask) - { - filter.name_mask = name_mask; - } else - { - filter.name_mask = ~0ULL; - } - ++filter_on; - } - - if (addr < 0xff) - { - filter.addr = addr; - if(addr_mask) - { - filter.addr_mask = addr_mask; - } else - { - filter.addr_mask = ~0; - } - ++filter_on; - } - if (pgn <= J1939_PGN_MAX) - { - filter.pgn = pgn; - if(pgn_mask) - { - filter.pgn_mask = pgn_mask; - } else - { - filter.pgn_mask = ~0; - } - ++filter_on; - } - if(filter_on) - { - setopt(SOL_CAN_J1939, SO_J1939_FILTER, &filter, sizeof(filter)); - } - } - - int socketcan_j1939_t::open(std::string device_name) - { - return open(device_name,0,0,0); - } - - int socketcan_j1939_t::open(std::string device_name, name_t name, pgn_t pgn, uint8_t addr) - { - - struct ifreq ifr; - socket_ = socketcan_t::open(PF_CAN, SOCK_DGRAM, CAN_J1939); - - // Attempts to open a socket to CAN bus - ::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_family = AF_CAN; - tx_address_.can_ifindex = ifr.ifr_ifindex; - - if(addr <= 0 || addr >= UINT8_MAX ) - { - tx_address_.can_addr.j1939.addr = J1939_NO_ADDR; - } - else - { - tx_address_.can_addr.j1939.addr = addr; - } - - if(name <= 0 || name >= UINT64_MAX ) - { - tx_address_.can_addr.j1939.name = J1939_NO_NAME; - } - else - { - tx_address_.can_addr.j1939.name = name; - } - - if(pgn <= 0 || pgn > J1939_PGN_MAX) - { - tx_address_.can_addr.j1939.pgn = J1939_NO_PGN; - } - else - { - tx_address_.can_addr.j1939.pgn = pgn; - } - - if(bind((struct sockaddr *)&tx_address_, sizeof(tx_address_)) < 0) - { - AFB_ERROR("Bind failed. %s", strerror(errno)); - close(); - } - else - { - int promisc = 1; // 0 = disabled (default), 1 = enabled - setopt(SOL_CAN_J1939, SO_J1939_PROMISC, &promisc, sizeof(promisc)); - int recv_own_msgs = 1; // 0 = disabled (default), 1 = enabled - setopt(SOL_CAN_J1939, SO_J1939_RECV_OWN, &recv_own_msgs, sizeof(recv_own_msgs)); - if(tx_address_.can_addr.j1939.pgn != J1939_NO_PGN) - { - filter(J1939_NO_NAME,tx_address_.can_addr.j1939.pgn,J1939_NO_ADDR); - } - } - } - return socket_; - } - - std::shared_ptr<message_t> socketcan_j1939_t::read_message() - { - std::shared_ptr<j1939_message_t> jm = std::make_shared<j1939_message_t>(); - uint8_t data[128] = {0}; - - struct sockaddr_can addr; - socklen_t addrlen = sizeof(addr); - struct ifreq ifr; - - ssize_t nbytes = ::recvfrom(socket(), &data, sizeof(data), 0, (struct sockaddr*)&addr, &addrlen); - ifr.ifr_ifindex = get_tx_address().can_ifindex; - ioctl(socket(), SIOCGIFNAME, &ifr); - - AFB_DEBUG("Data available: %i bytes read", (int)nbytes); - /*AFB_DEBUG("read: Found on bus %s:\n id: %X, length: %X, data %02X%02X%02X%02X%02X%02X%02X%02X", ifr.ifr_name, frame.can_id, frame.len, - data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);*/ - - struct timeval tv; - ioctl(socket(), SIOCGSTAMP, &tv); - uint64_t timestamp = 1000000 * tv.tv_sec + tv.tv_usec; - jm = j1939_message_t::convert_from_addr(addr, data , nbytes, timestamp); - jm->set_sub_id((int)socket()); - return jm; - } - - - void socketcan_j1939_t::write_message(std::vector<std::shared_ptr<message_t>>& vobj) - { - AFB_WARNING("Not implemented"); - } - - void socketcan_j1939_t::write_message(std::shared_ptr<message_t> cm) - { - AFB_WARNING("Not implemented"); - } - -} |