Author SHA1 Message Date
Paul Hollinsky f7e4af48c2 Use libicsneo with checksum failure logging code
Checksum failures will log to stderr
2019-11-06 10:25:18 -05:00
6 changed files with 28 additions and 60 deletions
-11
View File
@@ -1,14 +1,3 @@
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 v2.0.2
Use libicsneo v0.1.2 to resolve LEDs not indicating device status Use libicsneo v0.1.2 to resolve LEDs not indicating device status
+2 -2
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.2) cmake_minimum_required(VERSION 3.2)
project(libicsneo-socketcan-daemon VERSION 2.1.0) project(libicsneo-socketcan-daemon VERSION 2.0.2)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 11)
include(GNUInstallDirs) include(GNUInstallDirs)
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2016-2022 Intrepid Control Systems, Inc. Copyright (c) 2016-2019 Intrepid Control Systems, Inc.
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
+5 -5
View File
@@ -1,18 +1,18 @@
Version 2.1.0 Version 2.0.2
This is the usermode daemon for the Intrepid Control Systems SocketCAN support. This daemon requires that ```intrepid.ko``` is loaded on your system. 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). 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, libusb-1.0-0-dev, and libpcap. 2. Install the dependencies needed. These are CMake 3.2+, GCC 4.8+, git, and libusb-1.0-0-dev.
On Ubuntu or other Debian-based systems, run `sudo apt install git cmake gcc libusb-1.0-0-dev libpcap-dev build-essential`. On Ubuntu or other Debian-based systems, run `sudo apt install git cmake gcc libusb-1.0-0-dev build-essential`.
3. Clone this repository recursively by running `git clone --recursive https://github.com/intrepidcs/icsscand.git` 3. Clone this repository recursively by running `git clone --recursive https://github.com/intrepidcs/icsscand.git`
4. Switch into the cloned directory, `cd icsscand` 4. Switch into the cloned directory, `cd icsscand`
5. Make a build directory and switch into it, `mkdir build && cd build` 5. Make a build directory and switch into it, `mkdir -p build && cd build`
6. Invoke CMake, `cmake .. -DCMAKE_BUILD_TYPE=Release` 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. 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 can0 up`, replacing `can0` with whichever interface you'd like to enable 11. Enable the CAN interface with `sudo ip link set up can0`, 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. 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.
+19 -40
View File
@@ -20,8 +20,6 @@
#include <icsneo/icsneocpp.h> #include <icsneo/icsneocpp.h>
#include <icsneo/communication/message/neomessage.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 <icsneo/communication/message/callback/canmessagecallback.h>
#include <generated/buildinfo.h> #include <generated/buildinfo.h>
@@ -51,7 +49,6 @@ int driverPatch = 0;
int maxInterfaces = 0; // From driver int maxInterfaces = 0; // From driver
int sharedMemSize = 0; // From driver int sharedMemSize = 0; // From driver
void* sharedMemory = nullptr; void* sharedMemory = nullptr;
std::string serialFilter;
std::atomic<bool> stopRunning(false); std::atomic<bool> stopRunning(false);
@@ -88,15 +85,8 @@ public:
const std::string& getName() const { return name; } const std::string& getName() const { return name; }
uint8_t* getRxBox() { return rxBox; } uint8_t* getRxBox() { return rxBox; }
const uint8_t* getRxBox() const { return rxBox; } const uint8_t* getRxBox() const { return rxBox; }
void addReceivedMessageToQueue(const std::shared_ptr<icsneo::CANMessage>& msg) { void addReceivedMessageToQueue(const std::shared_ptr<icsneo::Message>& msg) {
const auto neomessageGeneric = icsneo::CreateNeoMessage(msg); auto neomessage = icsneo::CreateNeoMessage(msg);
if (neomessageGeneric.messageType != neomessagetype_t(icsneo::Message::Type::Frame)) {
LOG(LOG_DEBUG, "could not create a neomessage_can_t\n");
return;
}
const auto& neomessage = *reinterpret_cast<const neomessage_can_t*>(&neomessageGeneric);
size_t bytesNeeded = sizeof(neomessage) + neomessage.length; size_t bytesNeeded = sizeof(neomessage) + neomessage.length;
std::lock_guard<std::mutex> lg(rxBoxLock); std::lock_guard<std::mutex> lg(rxBoxLock);
if(ssize_t((rxBoxCurrentPosition - rxBox) + bytesNeeded) > RX_BOX_SIZE) { if(ssize_t((rxBoxCurrentPosition - rxBox) + bytesNeeded) > RX_BOX_SIZE) {
@@ -197,13 +187,12 @@ void header() {
void usage(std::string executableName) { void usage(std::string executableName) {
std::cerr << "The libicsneo SocketCAN Usermode Daemon\n"; std::cerr << "The libicsneo SocketCAN Usermode Daemon\n";
std::cerr << "Copyright 2019-2022 Intrepid Control Systems, Inc.\n\n"; std::cerr << "Copyright Intrepid Control Systems, Inc. 2019\n\n";
std::cerr << "Usage: " << executableName << " [option]\n\n"; std::cerr << "Usage: " << executableName << " [option]\n\n";
std::cerr << "Options:\n"; std::cerr << "Options:\n";
std::cerr << "\t-d, --daemon\t\tRun as a daemon in the background\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-h, -?, --help, --usage\t\tShow this help page\n";
std::cerr << "\t --devices\t\tList supported devices\n"; std::cerr << "\t --devices\t\tList supported devices\n";
std::cerr << "\t --filter <serial>\tOnly connect to devices with serial\n\t\t\t\t\tnumbers starting with this filter\n";
} }
void terminateSignal(int signal) { void terminateSignal(int signal) {
@@ -226,21 +215,16 @@ void searchForDevices() {
if(alreadyOpen) if(alreadyOpen)
continue; 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 // Now open the device
OpenDevice newDevice(dev); OpenDevice newDevice(dev);
const std::string serial = newDevice.device->getSerial();
Lazy<bool> firstTimeFailedToOpen([&serial]() { Lazy<bool> firstTimeFailedToOpen([&serial]() {
return std::find(failedToOpen.begin(), failedToOpen.end(), serial) == failedToOpen.end(); return std::find(failedToOpen.begin(), failedToOpen.end(), serial) == failedToOpen.end();
}); });
if(!newDevice.device->open() || !newDevice.device->goOnline()) { if(!newDevice.device->open() || !newDevice.device->goOnline()) {
if(firstTimeFailedToOpen) { if(firstTimeFailedToOpen) {
const std::string err = icsneo::GetLastError().describe(); icsneo::APIEvent err = icsneo::GetLastError();
LOGF(LOG_INFO, "%s failed to connect. Will keep trying...\n%s\n", newDevice.device->describe().c_str(), err.c_str()); LOGF(LOG_INFO, "%s failed to connect. Will keep trying...\n%s\n", newDevice.device->describe().c_str(), err.describe().c_str());
failedToOpen.push_back(serial); failedToOpen.push_back(serial);
} }
continue; continue;
@@ -286,9 +270,10 @@ void searchForDevices() {
// Create rx listener // Create rx listener
newDevice.device->addMessageCallback(icsneo::CANMessageCallback([serial](std::shared_ptr<icsneo::Message> message) { 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); auto canMessage = std::static_pointer_cast<icsneo::CANMessage>(message);
const OpenDevice* openDevice = nullptr; const OpenDevice* openDevice = nullptr;
std::lock_guard<std::mutex> lg(openDevicesMutex);
for(const auto& dev : openDevices) { for(const auto& dev : openDevices) {
if(dev.device->getSerial() == serial) { if(dev.device->getSerial() == serial) {
openDevice = &dev; openDevice = &dev;
@@ -358,8 +343,13 @@ void deviceSearchThread() {
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
for(int i = 1; i != argc; i++) { if(argc > 2) {
const std::string arg = argv[i]; usage(argv[0]);
return EX_USAGE;
}
if(argc == 2) {
const std::string arg = argv[1];
if(arg == "-d" || arg == "--daemon") { if(arg == "-d" || arg == "--daemon") {
runningAsDaemon = true; runningAsDaemon = true;
} else if(arg == "-h" || arg == "--help" || arg == "-?" || arg == "--usage") { } else if(arg == "-h" || arg == "--help" || arg == "-?" || arg == "--usage") {
@@ -371,9 +361,6 @@ int main(int argc, char** argv) {
for(auto& dev : icsneo::GetSupportedDevices()) for(auto& dev : icsneo::GetSupportedDevices())
std::cout << '\t' << dev << std::endl; std::cout << '\t' << dev << std::endl;
return EXIT_SUCCESS; return EXIT_SUCCESS;
} else if(arg == "--filter" && i + 1 <= argc) {
serialFilter = argv[++i];
transform(serialFilter.begin(), serialFilter.end(), serialFilter.begin(), ::toupper);
} else { } else {
usage(argv[0]); usage(argv[0]);
return EX_USAGE; return EX_USAGE;
@@ -489,26 +476,18 @@ int main(int argc, char** argv) {
// Send! // Send!
uint8_t* currentPosition = GET_TX_BOX(info.tx_box_index); uint8_t* currentPosition = GET_TX_BOX(info.tx_box_index);
while(info.count--) { while(info.count--) {
neomessage_frame_t* msg = reinterpret_cast<neomessage_frame_t*>(currentPosition); neomessage_t* msg = reinterpret_cast<neomessage_t*>(currentPosition);
currentPosition += sizeof(neomessage_frame_t); currentPosition += sizeof(neomessage_t);
msg->data = currentPosition; msg->data = currentPosition;
currentPosition += msg->length; currentPosition += msg->length;
if(msg->type != neonettype_t(icsneo::Network::Type::CAN)) {
LOG(LOG_ERR, "Message dropped, kernel sent a non-CAN message\n");
continue;
}
bool sent = false; bool sent = false;
std::lock_guard<std::mutex> lg(openDevicesMutex);
for(auto& dev : openDevices) { for(auto& dev : openDevices) {
for(auto& netifPair : dev.interfaces) { for(auto& netifPair : dev.interfaces) {
if(netifPair.second->getKernelHandle() != msg->netid) if(netifPair.second->getKernelHandle() != msg->netid)
continue; continue;
msg->netid = static_cast<uint16_t>(netifPair.first); msg->netid = static_cast<uint16_t>(netifPair.first);
auto txMsg = icsneo::CreateMessageFromNeoMessage(reinterpret_cast<neomessage_t*>(msg)); auto tx = icsneo::CreateMessageFromNeoMessage(msg);
auto tx = std::dynamic_pointer_cast<icsneo::Frame>(txMsg); if(!dev.device->transmit(tx))
if(!tx || !dev.device->transmit(tx))
break; break;
sent = true; sent = true;
break; break;