diff options
author | Romain Forlot <romain.forlot@iot.bzh> | 2017-04-20 00:07:37 +0200 |
---|---|---|
committer | Romain Forlot <romain.forlot@iot.bzh> | 2017-04-20 00:07:37 +0200 |
commit | f546e121079088920e2a3f64bc054afa05ff945f (patch) | |
tree | 4b966d3b97b3666cdb5b263c1b3be3f2b563db42 /CAN-binder | |
parent | ff30daa04391f981e871f1dea27b6fbb2b91791c (diff) |
Specializing socket class to CAN socket operations.
Move all legacy opening RAW CAN socket operation to socket class. Each operations
on a CAN socket has to be simple and made by the socket class.
Simple BCM socket open operation is implemented.
Future will be to open specialized BCM CAN sockets on demand.
Change-Id: If285b97afb9871245ab1f13cd9f0401fbd9adf95
Signed-off-by: Romain Forlot <romain.forlot@iot.bzh>
Diffstat (limited to 'CAN-binder')
-rw-r--r-- | CAN-binder/low-can-binding/can/can-bus-dev.cpp | 57 | ||||
-rw-r--r-- | CAN-binder/low-can-binding/can/can-bus-dev.hpp | 5 | ||||
-rw-r--r-- | CAN-binder/low-can-binding/can/can-bus.cpp | 2 | ||||
-rw-r--r-- | CAN-binder/low-can-binding/utils/socket.cpp | 85 | ||||
-rw-r--r-- | CAN-binder/low-can-binding/utils/socket.hpp | 25 |
5 files changed, 109 insertions, 65 deletions
diff --git a/CAN-binder/low-can-binding/can/can-bus-dev.cpp b/CAN-binder/low-can-binding/can/can-bus-dev.cpp index fb76498..6fab8e9 100644 --- a/CAN-binder/low-can-binding/can/can-bus-dev.cpp +++ b/CAN-binder/low-can-binding/can/can-bus-dev.cpp @@ -19,9 +19,6 @@ #include <map> #include <mutex> #include <unistd.h> -#include <string.h> -#include <net/if.h> -#include <sys/ioctl.h> #include <linux/can/raw.h> #include "can-bus-dev.hpp" @@ -54,63 +51,42 @@ uint32_t can_bus_dev_t::get_address() const /// timestamp received messages and pass the socket to FD mode. /// /// @return -1 if something wrong. -int can_bus_dev_t::open() +int can_bus_dev_t::open_raw() { const int canfd_on = 1; const int timestamp_on = 1; - struct ifreq ifr; struct timeval timeout; - DEBUG(binder_interface, "open: CAN Handler socket : %d", can_socket_.socket()); - if (can_socket_) - return 0; + DEBUG(binder_interface, "open_raw: CAN Handler socket : %d", can_socket_.socket()); + can_socket_.open(device_name_); - can_socket_.open(PF_CAN, SOCK_RAW, CAN_RAW); + // Set some option on the socket : timeout, timestamp and canfd frame usage. if (can_socket_) { - DEBUG(binder_interface, "open: CAN Handler socket correctly initialized : %d", can_socket_.socket()); + DEBUG(binder_interface, "open_raw: CAN Handler socket correctly initialized : %d", can_socket_.socket()); // Set timeout for read can_socket_.setopt(SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)); // Set timestamp for receveid frame if (can_socket_.setopt(SOL_SOCKET, SO_TIMESTAMP, ×tamp_on, sizeof(timestamp_on)) < 0) - WARNING(binder_interface, "open: setsockopt SO_TIMESTAMP error: %s", ::strerror(errno)); - DEBUG(binder_interface, "open: Switch CAN Handler socket to use fd mode"); + WARNING(binder_interface, "open_raw: setsockopt SO_TIMESTAMP error: %s", ::strerror(errno)); + DEBUG(binder_interface, "open_raw: Switch CAN Handler socket to use fd mode"); // try to switch the socket into CAN_FD mode if (can_socket_.setopt(SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on)) < 0) { - NOTICE(binder_interface, "open: Can not switch into CAN Extended frame format."); + NOTICE(binder_interface, "open_raw: Can not switch into CAN Extended frame format."); is_fdmode_on_ = false; } else { - DEBUG(binder_interface, "open: Correctly set up CAN socket to use FD frames."); + DEBUG(binder_interface, "open_raw: Correctly set up CAN socket to use FD frames."); is_fdmode_on_ = true; } - - // Attempts to open a socket to CAN bus - ::strcpy(ifr.ifr_name, device_name_.c_str()); - DEBUG(binder_interface, "open: ifr_name is : %s", ifr.ifr_name); - if(::ioctl(can_socket_.socket(), SIOCGIFINDEX, &ifr) < 0) - { - ERROR(binder_interface, "open: ioctl failed. Error was : %s", strerror(errno)); - } - else - { - txAddress_.can_family = AF_CAN; - txAddress_.can_ifindex = ifr.ifr_ifindex; - - // And bind it to txAddress - DEBUG(binder_interface, "Bind the socket"); - if (can_socket_.bind((struct sockaddr *)&txAddress_, sizeof(txAddress_)) < 0) - ERROR(binder_interface, "Bind failed. %s", strerror(errno)); - else return 0; - } - close(); } - else ERROR(binder_interface, "open: socket could not be created. Error was : %s", ::strerror(errno)); + else + ERROR(binder_interface, "open_raw: socket could not be created. Error was : %s", ::strerror(errno)); return -1; } @@ -199,8 +175,7 @@ int can_bus_dev_t::send(can_message_t& can_msg) if(can_socket_) { - nbytes = ::sendto(can_socket_.socket(), &f, sizeof(struct canfd_frame), 0, - (struct sockaddr*)&txAddress_, sizeof(txAddress_)); + nbytes = can_socket_.send(f); if (nbytes == -1) { ERROR(binder_interface, "send_can_message: Sending CAN frame failed."); @@ -211,7 +186,8 @@ int can_bus_dev_t::send(can_message_t& can_msg) else { ERROR(binder_interface, "send_can_message: socket not initialized. Attempt to reopen can device socket."); - open(); + open_raw(); + return -1; } return 0; } @@ -237,8 +213,7 @@ bool can_bus_dev_t::shims_send(const uint32_t arbitration_id, const uint8_t* dat if(can_socket_) { - nbytes = ::sendto(can_socket_.socket(), &f, sizeof(struct canfd_frame), 0, - (struct sockaddr*)&txAddress_, sizeof(txAddress_)); + nbytes = can_socket_.send(f); if (nbytes == -1) { ERROR(binder_interface, "send_can_message: Sending CAN frame failed."); @@ -249,7 +224,7 @@ bool can_bus_dev_t::shims_send(const uint32_t arbitration_id, const uint8_t* dat else { ERROR(binder_interface, "send_can_message: socket not initialized. Attempt to reopen can device socket."); - open(); + open_raw(); } return false; } diff --git a/CAN-binder/low-can-binding/can/can-bus-dev.hpp b/CAN-binder/low-can-binding/can/can-bus-dev.hpp index a612e7d..3e6b2d1 100644 --- a/CAN-binder/low-can-binding/can/can-bus-dev.hpp +++ b/CAN-binder/low-can-binding/can/can-bus-dev.hpp @@ -34,12 +34,11 @@ class can_bus_dev_t { private: std::string device_name_; ///< a string identifier identitfying the linux CAN device. - utils::socket_t can_socket_; + utils::socketcan_t can_socket_; int32_t address_; ///< an identifier used through binding that refer to that device bool is_fdmode_on_; ///< boolean telling if whether or not the can socket use fdmode. - struct sockaddr_can txAddress_; /// < internal member using to bind to the socket std::thread th_reading_; ///< Thread handling read the socket can device filling can_message_q_ queue of can_bus_t bool is_running_ = false; ///< boolean telling whether or not reading is running or not @@ -51,7 +50,7 @@ public: std::string get_device_name() const; uint32_t get_address() const; - int open(); + int open_raw(); int close(); void start_reading(can_bus_t& can_bus); diff --git a/CAN-binder/low-can-binding/can/can-bus.cpp b/CAN-binder/low-can-binding/can/can-bus.cpp index 61730a1..90d4c74 100644 --- a/CAN-binder/low-can-binding/can/can-bus.cpp +++ b/CAN-binder/low-can-binding/can/can-bus.cpp @@ -237,7 +237,7 @@ int can_bus_t::init_can_dev() for(const auto& device : devices_name) { can_bus_t::can_devices_[device] = std::make_shared<can_bus_dev_t>(device, i); - if (can_bus_t::can_devices_[device]->open() == 0) + if (can_bus_t::can_devices_[device]->open_raw() == 0) { DEBUG(binder_interface, "Start reading thread"); NOTICE(binder_interface, "%s device opened and reading", device.c_str()); diff --git a/CAN-binder/low-can-binding/utils/socket.cpp b/CAN-binder/low-can-binding/utils/socket.cpp index ee64348..e166b8c 100644 --- a/CAN-binder/low-can-binding/utils/socket.cpp +++ b/CAN-binder/low-can-binding/utils/socket.cpp @@ -16,24 +16,31 @@ */ #include <unistd.h> +#include <string> +#include <string.h> +#include <linux/can/raw.h> +#include <net/if.h> +#include <sys/ioctl.h> + #include "socket.hpp" +#include "low-can-binding.hpp" namespace utils { /// @brief Construct a default, invalid, socket. - socket_t::socket_t() + socketcan_t::socketcan_t() : socket_{INVALID_SOCKET} {} /// @brief Construct a socket by moving an existing one. - socket_t::socket_t(socket_t&& s) + socketcan_t::socketcan_t(socketcan_t&& s) : socket_{s.socket_} { s.socket_ = INVALID_SOCKET; } /// @brief Destruct the socket. - socket_t::~socket_t() + socketcan_t::~socketcan_t() { if(socket_ != INVALID_SOCKET) ::close(socket_); @@ -41,7 +48,7 @@ namespace utils /// @brief Test if socket is valid. /// @return true if valid, false otherwise. - socket_t::operator bool() const + socketcan_t::operator bool() const { return socket_ != INVALID_SOCKET; } @@ -51,7 +58,7 @@ namespace utils /// @param[in] type Specifies the type of socket to be created. /// @param[in] protocol Specifies a particular protocol to be used with the socket. Specifying a protocol of 0 causes socket() to use an unspecified default protocol appropriate for the requested socket type. /// @return Upon successful completion, shall return a non-negative integer, the socket file descriptor. Otherwise, a value of -1 shall be returned and errno set to indicate the error. - int socket_t::open(int domain, int type, int protocol) + int socketcan_t::open(int domain, int type, int protocol) { close(); socket_ = ::socket(domain, type, protocol); @@ -60,29 +67,89 @@ namespace utils /// @brief Close the socket. /// @return 0 if success. - int socket_t::close() + int socketcan_t::close() { return socket_ != INVALID_SOCKET ? ::close(socket_) : 0; } /// @brief Set socket option. /// @return 0 if success. - int socket_t::setopt(int level, int optname, const void* optval, socklen_t optlen) + int socketcan_t::setopt(int level, int optname, const void* optval, socklen_t optlen) { return socket_ != INVALID_SOCKET ? ::setsockopt(socket_, level, optname, optval, optlen) : 0; } /// @brief Bind the socket. /// @return 0 if success. - int socket_t::bind(const struct sockaddr* addr, socklen_t len) + int socketcan_t::bind(const struct sockaddr* addr, socklen_t len) { return socket_ != INVALID_SOCKET ? ::bind(socket_, addr, len) : 0; } + /// @brief Connect the socket. + /// @return 0 if success. + int socketcan_t::connect(const struct sockaddr* addr, socklen_t len) + { + return socket_ != INVALID_SOCKET ? ::connect(socket_, addr, len) : 0; + } + /// @brief Get the file descriptor. /// @return The socket's file descriptor - int socket_t::socket() const + int socketcan_t::socket() const + { + return socket_; + } + + /// @brief Open a raw socket CAN. + /// @param[in] device_name is the kernel network device name of the CAN interface. + /// + /// @return Upon successful completion, shall return a non-negative integer, the socket file descriptor. Otherwise, a value of -1 shall be returned and errno set to indicate the error. + int socketcan_t::open(std::string device_name, bool bcm) { + close(); + + struct ifreq ifr; + if(bcm) + socket_ = ::socket(PF_CAN, SOCK_DGRAM, CAN_BCM); + else + socket_ = ::socket(PF_CAN, SOCK_RAW, CAN_RAW); + + // Attempts to open a socket to CAN bus + ::strcpy(ifr.ifr_name, device_name.c_str()); + DEBUG(binder_interface, "open: ifr_name is : %s", ifr.ifr_name); + if(::ioctl(socket_, SIOCGIFINDEX, &ifr) < 0) + { + ERROR(binder_interface, "open: ioctl failed. Error was : %s", strerror(errno)); + close(); + } + else + { + txAddress_.can_family = AF_CAN; + txAddress_.can_ifindex = ifr.ifr_ifindex; + + if(bcm && connect((struct sockaddr *)&txAddress_, sizeof(txAddress_)) < 0) + { + ERROR(binder_interface, "Connect failed. %s", strerror(errno)); + close(); + } + // It's a RAW socket request, bind it to txAddress + else if(bind((struct sockaddr *)&txAddress_, sizeof(txAddress_)) < 0) + { + ERROR(binder_interface, "Bind failed. %s", strerror(errno)); + close(); + } + } return socket_; } + + /// @brief Send a CAN message through the socket. + /// + /// @param[in] f - the CAN FD frame to send + /// + /// @return number of sent bytes if message sent, 0 on invalid socket and -1 if something wrong. + ssize_t socketcan_t::send(const struct canfd_frame& f) + { + return socket_ != INVALID_SOCKET ? ::sendto(socket_, &f, sizeof(struct canfd_frame), 0, + (struct sockaddr*)&txAddress_, sizeof(txAddress_)) : 0; + } } diff --git a/CAN-binder/low-can-binding/utils/socket.hpp b/CAN-binder/low-can-binding/utils/socket.hpp index b42eee6..2da2dfe 100644 --- a/CAN-binder/low-can-binding/utils/socket.hpp +++ b/CAN-binder/low-can-binding/utils/socket.hpp @@ -23,24 +23,27 @@ namespace utils { - class socket_t + class socketcan_t { public: - socket_t(); - socket_t(const socket_t&) = delete; - socket_t(socket_t&&); - ~socket_t(); + socketcan_t(); + socketcan_t(const socketcan_t&) = delete; + socketcan_t(socketcan_t&&); + ~socketcan_t(); explicit operator bool() const; - int open(int domain, int type, int protocol); - int close(); - int setopt(int level, int optname, const void* optval, socklen_t optlen); int socket() const; - int bind(const struct sockaddr* addr, socklen_t len); - + int open(std::string device_name, bool bcm=false); + int setopt(int level, int optname, const void* optval, socklen_t optlen); + ssize_t send(const struct canfd_frame& f); + int close(); private: int socket_; + struct sockaddr_can txAddress_; /// < internal member using to bind to the socket + + int open(int domain, int type, int protocol); + int bind(const struct sockaddr* addr, socklen_t len); + int connect(const struct sockaddr* addr, socklen_t len); }; } - |