Author SHA1 Message Date
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 SikesandPaul Hollinsky 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 HollinskyandGitHub 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
6 changed files with 54 additions and 28 deletions
+5
View File
@@ -1,3 +1,8 @@
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
+2 -2
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.2)
project(libicsneo-socketcan-daemon VERSION 2.0.2)
project(libicsneo-socketcan-daemon VERSION 2.1.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
include(GNUInstallDirs)
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2016-2019 Intrepid Control Systems, Inc.
Copyright (c) 2016-2021 Intrepid Control Systems, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
+5 -5
View File
@@ -1,18 +1,18 @@
Version 2.0.2
Version 2.0.3
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.
+40 -19
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>
@@ -49,6 +51,7 @@ int driverPatch = 0;
int maxInterfaces = 0; // From driver
int sharedMemSize = 0; // From driver
void* sharedMemory = nullptr;
std::string serialFilter;
std::atomic<bool> stopRunning(false);
@@ -85,8 +88,15 @@ 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);
void addReceivedMessageToQueue(const std::shared_ptr<icsneo::CANMessage>& 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;
}
const auto& neomessage = *reinterpret_cast<const neomessage_can_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) {
@@ -187,12 +197,13 @@ 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-2020 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 --filter <serial>\tOnly connect to devices with serial\n\t\t\t\t\tnumbers starting with this filter\n";
}
void terminateSignal(int signal) {
@@ -215,16 +226,21 @@ 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::APIEvent err = icsneo::GetLastError();
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;
@@ -270,10 +286,9 @@ void searchForDevices() {
// 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);
const OpenDevice* openDevice = nullptr;
std::lock_guard<std::mutex> lg(openDevicesMutex);
for(const auto& dev : openDevices) {
if(dev.device->getSerial() == serial) {
openDevice = &dev;
@@ -343,13 +358,8 @@ void deviceSearchThread() {
}
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") {
@@ -361,6 +371,9 @@ 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 {
usage(argv[0]);
return EX_USAGE;
@@ -476,18 +489,26 @@ int main(int argc, char** argv) {
// 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)) {
LOG(LOG_ERR, "Message dropped, kernel sent a non-CAN 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;