Compare commits

...

29 Commits

Author SHA1 Message Date
Kyle Schwarz 2838f4488c Update libicsneo 2025-10-15 12:00:31 -04:00
Kyle Schwarz 8c7f306771 Update libicsneo 2025-06-19 19:21:59 -04:00
Kyle Schwarz 945a027b5b Update libicsneo 2025-05-07 10:02:46 -04:00
Kyle Schwarz 1acc51af7d Update copyright year to 2025 2025-05-07 10:02:27 -04:00
Christian Gabriel be51cce4f1 3.2.0
Signed-off-by: Christian Gabriel <ch_gabriel@web.de>
2024-07-23 15:13:32 -04:00
Christian Gabriel 8dbd767b3e Add support for bitrate setting
If kernel driver version is new enough, report the currently set
bitrates via ioctl.
Kernel will report changed bitrates through special read operations,
send these values to the device.

Signed-off-by: Christian Gabriel <ch_gabriel@web.de>
2024-07-23 15:13:26 -04:00
Kyle Schwarz 52db71754d 3.1.2 2024-01-02 10:16:28 -05:00
Kyle Schwarz d611db1318 Update libicsneo 2024-01-02 10:16:13 -05:00
Kyle Schwarz 707892e9b7 Update copyright year to 2024 2024-01-02 10:10:20 -05:00
kschwarz-intrepidcs 154c58792e
Merge pull request #13 from j-rge/add_scan_interval_param
Add scan-interval-ms parameter
2023-09-27 20:35:20 -04:00
Jorge Alejandro 1d0cdb9f00 Add scan-interval-ms parameter
Allow user to specify the scan interval for searching for devices.
Scanning places every interface on the machine in promiscuous mode
and currently runs once a second.  This behaviour may have undesirable
side-effects and also pollutes the kernel log.

The new parameter --scan-interval-ms <interval> will allow the user
to specify the rate at which scanning occurs.  If equal to 0, then
only a single scan is performed.
2023-09-17 18:13:21 -04:00
Kyle Schwarz b56fc99c2c Update libicsneo 2023-07-11 22:44:19 -04:00
Kyle Schwarz 3e96cc9105 3.1.0
Update libicsneo & copyright
2023-05-05 00:26:52 -04:00
Kyle Schwarz eca0ec0c25 Bump project version to match module 2022-09-01 13:15:46 -04:00
Gary Chong b33ec54593 Added Functionality for Ethernet 2022-08-16 15:31:35 -04:00
Paul Hollinsky b5d56bc740 v2.1.0
Update copyright date
Update to libicsneo v0.3.0
Report transmits down to the kernel for echo
Allow filtering devices by serial number
2022-03-31 18:18:33 -04:00
Paul Hollinsky 9ba6f2cec5 Update copyright date to 2022 2022-03-31 18:13:23 -04:00
Paul Hollinsky c7db3cbcf0 Refactor for libicsneo v0.3.0 API changes 2022-03-31 15:41:19 -04:00
Paul Hollinsky 616a8ddbce Report transmit receipts to kernel
These will be used for IFF_ECHO
2022-03-31 15:40:28 -04:00
Paul Hollinsky dcec89f2da Allow filtering devices by serial number 2022-03-31 13:51:03 -04:00
Paul Hollinsky 919bcccffc Fix arguments with the wrong ordering for ip link set 2021-04-28 10:27:31 -04:00
Kevin Sikes 26b676b474 Update copyright date for 2021 2021-04-15 15:40:55 -04:00
Paul Hollinsky c506f274c2 v2.0.3
Update copyright date
Update to libicsneo v0.2.0
Ensure lock is held when accessing open devices
2020-08-06 18:03:04 -04:00
Paul Hollinsky 8cc37c9df0 Update copyright date 2020-08-06 17:06:25 -04:00
Paul Hollinsky 028538cc90 Update to libicsneo v0.2.0 2020-08-06 17:02:12 -04:00
Paul Hollinsky 8d21b98ac6 Ensure lock is held when accessing open devices 2020-08-06 17:01:24 -04:00
Paul Hollinsky f254ee2515
Merge pull request #5 from vladionescu/master
Added libpcap to dependencies in README
2020-08-06 16:40:16 -04:00
Vlad Ionescu e83021258f Added libpcap to dependencies in README 2020-05-05 08:20:04 -07:00
Paul Hollinsky a69c41c9d5 v2.0.2
Use libicsneo v0.1.2 to resolve LEDs not indicating device status
2019-09-04 13:32:48 -04:00
6 changed files with 247 additions and 94 deletions

View File

@ -1,3 +1,32 @@
v3.1.2
Update libicsneo
Update copyright
Add scan-interval-ms parameter (Jorge Alejandro <jorge.a.alejandro@gmail.com>)
v3.1.1
Update libicsneo
v3.1.0
Update libicsneo
Update copyright
v3.0.0
Added Functionality for Ethernet
v2.1.0
Update copyright date
Update to libicsneo v0.3.0
Report transmits down to the kernel for echo
Allow filtering devices by serial number
v2.0.3
Update copyright date
Update to libicsneo v0.2.0
Ensure lock is held when accessing open devices
v2.0.2
Use libicsneo v0.1.2 to resolve LEDs not indicating device status
v2.0.1
Set timeout tv_sec instead of tv_usec for compatibility with older kernels

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneo-socketcan-daemon VERSION 2.0.1)
project(libicsneo-socketcan-daemon VERSION 3.2.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
include(GNUInstallDirs)

View File

@ -1,4 +1,4 @@
Copyright (c) 2016-2019 Intrepid Control Systems, Inc.
Copyright (c) 2016-2025 Intrepid Control Systems, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@ -1,18 +1,18 @@
Version 2.0.1
Version 3.1.2
This is the usermode daemon for the Intrepid Control Systems SocketCAN support. This daemon requires that ```intrepid.ko``` is loaded on your system.
1. Build and load the kernel module follwowing the instructions in [intrepid-socketcan-kernel-module](https://github.com/intrepidcs/intrepid-socketcan-kernel-module).
2. Install the dependencies needed. These are CMake 3.2+, GCC 4.8+, git, and libusb-1.0-0-dev.
2. Install the dependencies needed. These are CMake 3.2+, GCC 4.8+, git, libusb-1.0-0-dev, and libpcap.
On Ubuntu or other Debian-based systems, run `sudo apt install git cmake gcc libusb-1.0-0-dev build-essential`.
On Ubuntu or other Debian-based systems, run `sudo apt install git cmake gcc libusb-1.0-0-dev libpcap-dev build-essential`.
3. Clone this repository recursively by running `git clone --recursive https://github.com/intrepidcs/icsscand.git`
4. Switch into the cloned directory, `cd icsscand`
5. Make a build directory and switch into it, `mkdir -p build && cd build`
5. Make a build directory and switch into it, `mkdir build && cd build`
6. Invoke CMake, `cmake .. -DCMAKE_BUILD_TYPE=Release`
@ -24,6 +24,6 @@ On Ubuntu or other Debian-based systems, run `sudo apt install git cmake gcc lib
10. CAN interfaces will have been created, but are "down" or, in other words, not enabled for transmit and receive yet. You can see them with `ip link`. They will be labelled `can0`, `can1`, and etc. They will have an alias listed which corresponds to the serial number of the device and network on that device.
11. Enable the CAN interface with `sudo ip link set up can0`, replacing `can0` with whichever interface you'd like to enable
11. Enable the CAN interface with `sudo ip link set can0 up`, replacing `can0` with whichever interface you'd like to enable
12. You can now use any SocketCAN application with this interface. A good package for testing is the `can-utils` package. You can get this package with `sudo apt install can-utils`. A good testing tool which comes with this package is `candump`. Running `candump can0` will print a line for every incoming frame.

View File

@ -20,6 +20,8 @@
#include <icsneo/icsneocpp.h>
#include <icsneo/communication/message/neomessage.h>
#include <icsneo/communication/message/message.h>
#include <icsneo/communication/network.h>
#include <icsneo/communication/message/callback/canmessagecallback.h>
#include <generated/buildinfo.h>
@ -28,19 +30,24 @@
#define LOGF(LVL, MSG, ...) do{if(runningAsDaemon) syslog(LVL, MSG, __VA_ARGS__); \
else fprintf(stderr, MSG, __VA_ARGS__);}while(0)
#define SIOCSADDIF 0x3001
#define SIOCSREMOVEIF 0x3002
#define SIOCGSHAREDMEMSIZE 0x3003
#define SIOCSMSGSWRITTEN 0x3004
#define SIOCGMAXIFACES 0x3005
#define SIOCGVERSION 0x3006
#define SIOCGCLIENTVEROK 0x3007
#define SIOCSADDCANIF 0x3001
#define SIOCSADDETHIF 0x3002
#define SIOCSREMOVECANIF 0x3003
#define SIOCSREMOVEETHIF 0x3004
#define SIOCGSHAREDMEMSIZE 0x3005
#define SIOCSMSGSWRITTEN 0x3006
#define SIOCGMAXIFACES 0x3007
#define SIOCGVERSION 0x3008
#define SIOCGCLIENTVEROK 0x3009
#define SIOCSBAUDRATE 0x300A
#define RX_BOX_SIZE (sharedMemSize / (maxInterfaces * 2))
#define TX_BOX_SIZE (sharedMemSize / 4)
#define GET_RX_BOX(DEVICE_INDEX) (reinterpret_cast<uint8_t*>(sharedMemory) + (RX_BOX_SIZE * DEVICE_INDEX))
#define GET_TX_BOX(INDEX) (reinterpret_cast<uint8_t*>(sharedMemory) + (sharedMemSize / 2) + (INDEX * TX_BOX_SIZE))
#define DEFAULT_SCAN_INTERVAL_MS 1000
bool runningAsDaemon = false;
int driver = 0; // /dev/intrepid_netdevice
int driverMajor = 0;
@ -49,6 +56,8 @@ int driverPatch = 0;
int maxInterfaces = 0; // From driver
int sharedMemSize = 0; // From driver
void* sharedMemory = nullptr;
std::string serialFilter;
int scanIntervalMs = DEFAULT_SCAN_INTERVAL_MS;
std::atomic<bool> stopRunning(false);
@ -60,10 +69,16 @@ struct intrepid_pending_tx_info {
class NetworkInterface {
public:
NetworkInterface(const std::string& desiredName) : name(desiredName) {
NetworkInterface(const std::string& desiredName, icsneo::Network::Type device) : type(device), name(desiredName) {
char ifname[IFALIASZ + 1] = {0};
strncpy(ifname, name.c_str(), IFALIASZ);
kernelHandle = ioctl(driver, SIOCSADDIF, ifname);
if(device == icsneo::Network::Type::CAN) {
kernelHandle = ioctl(driver, SIOCSADDCANIF, ifname); // this will call the intrepid_dev_ioctl()
} else if(device == icsneo::Network::Type::Ethernet) {
kernelHandle = ioctl(driver, SIOCSADDETHIF, ifname); // this will call the intrepid_dev_ioctl()
}
if(openedSuccessfully()) {
rxBox = GET_RX_BOX(kernelHandle);
rxBoxCurrentPosition = rxBox;
@ -71,12 +86,36 @@ public:
}
~NetworkInterface() {
if(openedSuccessfully()) {
int res = 0;
LOGF(LOG_DEBUG, "Removing device %s with handle %d\n", name.c_str(), kernelHandle);
int res = ioctl(driver, SIOCSREMOVEIF, kernelHandle);
if(type == icsneo::Network::Type::CAN) {
res = ioctl(driver, SIOCSREMOVECANIF, kernelHandle);
} else if(type == icsneo::Network::Type::Ethernet) {
res = ioctl(driver, SIOCSREMOVEETHIF, kernelHandle);
}
LOGF(LOG_DEBUG, "Removed device %s with handle %d, result %d\n", name.c_str(), kernelHandle, res);
} else
LOG(LOG_DEBUG, "Removing interface which was not opened successfully\n");
}
bool reportBaudrates(int64_t baudrate, int64_t fd_baudrate) {
struct baudrate_info {
int handle;
int64_t baudrates[2];
} info;
info.handle = kernelHandle;
info.baudrates[0] = baudrate;
/* set fd baudrate to zero if equal to baudrate
* this will disable fd mode in kernel */
info.baudrates[1] = (fd_baudrate==baudrate)?0:fd_baudrate;
if (ioctl(driver, SIOCSBAUDRATE, &info) != 0) {
LOGF(LOG_INFO, "Unable to set baudrate for device %s\n", name.c_str());
return false;
}
return true;
}
NetworkInterface(const NetworkInterface&) = delete;
NetworkInterface& operator =(const NetworkInterface&) = delete;
@ -85,8 +124,19 @@ public:
const std::string& getName() const { return name; }
uint8_t* getRxBox() { return rxBox; }
const uint8_t* getRxBox() const { return rxBox; }
void addReceivedMessageToQueue(const std::shared_ptr<icsneo::Message>& msg) {
auto neomessage = icsneo::CreateNeoMessage(msg);
template<typename T>
void addReceivedMessageToQueue(const std::shared_ptr<icsneo::Frame>& msg) {
const auto neomessageGeneric = icsneo::CreateNeoMessage(msg);
if(neomessageGeneric.messageType != neomessagetype_t(icsneo::Message::Type::Frame)) {
LOG(LOG_DEBUG, "could not create a neomessage_can_t\n");
return;
}
if(msg->network.getType() == icsneo::Network::Type::CAN || msg->network.getType() == icsneo::Network::Type::Ethernet) {
const auto& neomessage = *reinterpret_cast<const T*>(&neomessageGeneric);
size_t bytesNeeded = sizeof(neomessage) + neomessage.length;
std::lock_guard<std::mutex> lg(rxBoxLock);
if(ssize_t((rxBoxCurrentPosition - rxBox) + bytesNeeded) > RX_BOX_SIZE) {
@ -106,8 +156,10 @@ public:
rxBoxCurrentPosition = rxBox;
rxBoxMessageCount = 0;
}
}
private:
icsneo::Network::Type type;
std::string name;
int kernelHandle = -1;
std::mutex rxBoxLock;
@ -170,7 +222,7 @@ std::string sanitizeInterfaceName(std::string str) {
void header() {
std::cout << "The libicsneo SocketCAN Usermode Daemon\n";
std::cout << "Copyright Intrepid Control Systems, Inc. 2019\n\n";
std::cout << "Copyright Intrepid Control Systems, Inc. 2025\n\n";
std::cout << "Daemon v";
std::cout << (int)ICSNEO_SOCKETCAN_BUILD_MAJOR << '.' << (int)ICSNEO_SOCKETCAN_BUILD_MINOR << '.' << (int)ICSNEO_SOCKETCAN_BUILD_PATCH;
if(ICSNEO_SOCKETCAN_BUILD_METADATA[0] != '\0')
@ -187,12 +239,14 @@ void header() {
void usage(std::string executableName) {
std::cerr << "The libicsneo SocketCAN Usermode Daemon\n";
std::cerr << "Copyright Intrepid Control Systems, Inc. 2019\n\n";
std::cerr << "Copyright 2019-2025 Intrepid Control Systems, Inc.\n\n";
std::cerr << "Usage: " << executableName << " [option]\n\n";
std::cerr << "Options:\n";
std::cerr << "\t-d, --daemon\t\tRun as a daemon in the background\n";
std::cerr << "\t-h, -?, --help, --usage\t\tShow this help page\n";
std::cerr << "\t --devices\t\tList supported devices\n";
std::cerr << "\t-d, --daemon\t\t\tRun as a daemon in the background\n";
std::cerr << "\t-h, -?, --help, --usage\t\t\tShow this help page\n";
std::cerr << "\t --devices\t\t\tList supported devices\n";
std::cerr << "\t --filter <serial>\t\tOnly connect to devices with serial\n\t\t\t\t\t\tnumbers starting with this filter\n";
std::cerr << "\t --scan-interval-ms <interval>\tDevice scan interval in ms\n\t\t\t\t\t\tIf 0, only a single scan is performed\n";
}
void terminateSignal(int signal) {
@ -215,43 +269,48 @@ void searchForDevices() {
if(alreadyOpen)
continue;
const std::string serial = dev->getSerial();
// If we have a serial filter, make sure our serial starts with the given filter
if(!serialFilter.empty() && serial.rfind(serialFilter, 0) != 0)
continue;
// Now open the device
OpenDevice newDevice(dev);
const std::string serial = newDevice.device->getSerial();
Lazy<bool> firstTimeFailedToOpen([&serial]() {
return std::find(failedToOpen.begin(), failedToOpen.end(), serial) == failedToOpen.end();
});
if(!newDevice.device->open() || !newDevice.device->goOnline()) {
if(firstTimeFailedToOpen) {
icsneo::APIError err;
icsneo::GetLastError(err);
LOGF(LOG_INFO, "%s failed to connect. Will keep trying...\n%s\n", newDevice.device->describe().c_str(), err.describe().c_str());
const std::string err = icsneo::GetLastError().describe();
LOGF(LOG_INFO, "%s failed to connect. Will keep trying...\n%s\n", newDevice.device->describe().c_str(), err.c_str());
failedToOpen.push_back(serial);
}
continue;
}
// Get the supported CAN networks
// Get the supported networks
auto supportedNetworks = newDevice.device->getSupportedRXNetworks();
supportedNetworks.erase(std::remove_if(supportedNetworks.begin(), supportedNetworks.end(), [](const icsneo::Network& net) -> bool {
return net.getType() != icsneo::Network::Type::CAN;// Only want CAN networks
return net.getType() != icsneo::Network::Type::CAN && net.getType() != icsneo::Network::Type::Ethernet;
}), supportedNetworks.end());
if(supportedNetworks.empty()) {
if(firstTimeFailedToOpen) {
LOGF(LOG_INFO, "%s has no supported CAN networks\n", newDevice.device->describe().c_str());
LOGF(LOG_INFO, "%s has no supported networks\n", newDevice.device->describe().c_str());
failedToOpen.push_back(serial);
}
continue;
}
// Create a network interface for each CAN network
// Create a network interface for each network
for(const auto& net : supportedNetworks) {
std::stringstream ss;
ss << sanitizeInterfaceName(icsneo::Network::GetNetIDString(net.getNetID())) << "_" << serial;
std::string interfaceName(ss.str());
if(firstTimeFailedToOpen)
LOGF(LOG_INFO, "Creating network interface %s\n", interfaceName.c_str());
newDevice.interfaces[net.getNetID()] = std::make_shared<NetworkInterface>(interfaceName);
newDevice.interfaces[net.getNetID()] = std::make_shared<NetworkInterface>(interfaceName, net.getType());
LOGF(LOG_INFO, "Created network interface %s\n", interfaceName.c_str());
}
bool failedToCreateNetworkInterfaces = false;
@ -268,26 +327,40 @@ void searchForDevices() {
}
continue;
}
if (driverMinor > 0) {
for(const auto& net : supportedNetworks) {
if (net.getType() != icsneo::Network::Type::CAN)
continue;
newDevice.interfaces[net.getNetID()]->reportBaudrates(
newDevice.device->settings->getBaudrateFor(net.getNetID()),
newDevice.device->settings->getFDBaudrateFor(net.getNetID())
);
}
}
// Create rx listener
newDevice.device->addMessageCallback(icsneo::CANMessageCallback([serial](std::shared_ptr<icsneo::Message> message) {
if(message->transmitted)
return;
auto canMessage = std::static_pointer_cast<icsneo::CANMessage>(message);
newDevice.device->addMessageCallback(std::make_shared<icsneo::MessageCallback>([serial](std::shared_ptr<icsneo::Message> message) {
const auto frame = std::static_pointer_cast<icsneo::Frame>(message);
const auto messageType = frame->network.getType();
const OpenDevice* openDevice = nullptr;
std::lock_guard<std::mutex> lg(openDevicesMutex);
for(const auto& dev : openDevices) {
if(dev.device->getSerial() == serial) {
openDevice = &dev;
break;
}
}
if(!openDevice) {
LOG(LOG_ERR, "Dropping message, no open device\n");
if(frame->type != icsneo::Message::Type::Frame) {
LOG(LOG_ERR, "Dropping message: received invalid message type, expected RawMessage\n");
return;
}
// todo might throw
openDevice->interfaces.at(canMessage->network.getNetID())->addReceivedMessageToQueue(canMessage);
if(messageType == icsneo::Network::Type::CAN) {
openDevice->interfaces.at(frame->network.getNetID())->addReceivedMessageToQueue<neomessage_can_t>(frame);
} else if(messageType == icsneo::Network::Type::Ethernet) {
openDevice->interfaces.at(frame->network.getNetID())->addReceivedMessageToQueue<neomessage_eth_t>(frame);
} else
LOG(LOG_ERR, "Dropping message, only CAN and Ethernet are currently supported\n");
}));
LOGF(LOG_INFO, "%s connected\n", newDevice.device->describe().c_str());
@ -320,7 +393,7 @@ void searchForDevices() {
openDevices.end()
);
for(const auto& err : icsneo::GetErrors()) {
for(const auto& err : icsneo::GetEvents()) {
bool forErrorDevice = false;
for(const auto& dev : failedToOpen) {
if(err.isForDevice(dev)) {
@ -339,18 +412,16 @@ void searchForDevices() {
void deviceSearchThread() {
while(!stopRunning) {
searchForDevices();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
if(scanIntervalMs == 0) {
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(scanIntervalMs));
}
}
int main(int argc, char** argv) {
if(argc > 2) {
usage(argv[0]);
return EX_USAGE;
}
if(argc == 2) {
const std::string arg = argv[1];
for(int i = 1; i != argc; i++) {
const std::string arg = argv[i];
if(arg == "-d" || arg == "--daemon") {
runningAsDaemon = true;
} else if(arg == "-h" || arg == "--help" || arg == "-?" || arg == "--usage") {
@ -362,6 +433,24 @@ int main(int argc, char** argv) {
for(auto& dev : icsneo::GetSupportedDevices())
std::cout << '\t' << dev << std::endl;
return EXIT_SUCCESS;
} else if(arg == "--filter" && i + 1 <= argc) {
serialFilter = argv[++i];
transform(serialFilter.begin(), serialFilter.end(), serialFilter.begin(), ::toupper);
} else if(arg == "--scan-interval-ms" && i + 1 <= argc) {
try {
scanIntervalMs = std::stoi(argv[++i]);
} catch (const std::invalid_argument& e) {
std::cerr << "Invalid input for scan-interval-ms\n";
return EX_USAGE;
} catch (const std::out_of_range& e) {
std::cerr << "Out of range input for scan-interval-ms\n";
return EX_USAGE;
}
if(scanIntervalMs < 0) {
std::cerr << "Invalid input for scan-interval-ms\n";
return EX_USAGE;
}
} else {
usage(argv[0]);
return EX_USAGE;
@ -405,7 +494,7 @@ int main(int argc, char** argv) {
return EXIT_FAILURE;
}
std::cout << "Driver v" << driverMajor << '.' << driverMinor << '.' << driverPatch << "\n\n";
if(driverMajor > 2) {
if(driverMajor > 3) {
LOG(LOG_ERR, "This version of the usermode daemon is too old to work with this driver\nPlease ensure that both the usermode daemon and kernel driver are up to date\n");
return EXIT_FAILURE;
}
@ -473,22 +562,57 @@ int main(int argc, char** argv) {
LOGF(LOG_ERR, "Unexpected number of bytes read, expected %d got %d\n", (int)sizeof(info), (int)r);
stopRunning = true;
break;
} else if (info.tx_box_index < 0) {
// Baudrate changed in kernel
int dev_idx = -(info.tx_box_index + 1);
LOGF(LOG_INFO, "Baudrate change, device %d, baudrate %d fd_baudrate %ld\n",
dev_idx, info.count, info.bytes);
/* fd baudrate is zero if fd mode is disabled in kernel
* set fd baudrate equal to baudrate */
if (info.bytes == 0) {
info.bytes = info.count;
}
for(auto& dev : openDevices) {
for(auto& netifPair : dev.interfaces) {
auto netid = netifPair.first;
if(netifPair.second->getKernelHandle() != dev_idx)
continue;
if (! dev.device->settings->setBaudrateFor(netid, info.count) ) {
LOGF(LOG_ERR, "Unable to set baudrate for device %s\n",
netifPair.second->getName().c_str());
} else if (! dev.device->settings->setFDBaudrateFor(netid, info.bytes)) {
LOGF(LOG_ERR, "Unable to set fd baudrate for device %s\n",
netifPair.second->getName().c_str());
} else if (! dev.device->settings->apply()) {
LOGF(LOG_ERR, "Unable to apply settings for device %s\n",
netifPair.second->getName().c_str());
}
}
}
} else {
// Send!
uint8_t* currentPosition = GET_TX_BOX(info.tx_box_index);
while(info.count--) {
neomessage_t* msg = reinterpret_cast<neomessage_t*>(currentPosition);
currentPosition += sizeof(neomessage_t);
neomessage_frame_t* msg = reinterpret_cast<neomessage_frame_t*>(currentPosition);
currentPosition += sizeof(neomessage_frame_t);
msg->data = currentPosition;
currentPosition += msg->length;
if(msg->type != neonettype_t(icsneo::Network::Type::CAN) && msg->type != neonettype_t(icsneo::Network::Type::Ethernet)) {
LOG(LOG_ERR, "Message dropped, kernel sent a non-CAN/Ethernet message\n");
continue;
}
bool sent = false;
std::lock_guard<std::mutex> lg(openDevicesMutex);
for(auto& dev : openDevices) {
for(auto& netifPair : dev.interfaces) {
if(netifPair.second->getKernelHandle() != msg->netid)
continue;
msg->netid = static_cast<uint16_t>(netifPair.first);
auto tx = icsneo::CreateMessageFromNeoMessage(msg);
if(!dev.device->transmit(tx))
auto txMsg = icsneo::CreateMessageFromNeoMessage(reinterpret_cast<neomessage_t*>(msg));
auto tx = std::dynamic_pointer_cast<icsneo::Frame>(txMsg);
if(!tx || !dev.device->transmit(tx))
break;
sent = true;
break;

@ -1 +1 @@
Subproject commit 0b4ffdbaad66904926623a6ed3800effd1d9ff42
Subproject commit deabc2cff438819c3a18a6325ba6fce080d3882c