CAN bus support in Alpine
Alpine should support the CAN bus protocol which is widely used to communicate between components in vehicles.
Kernel.org already contains the modules for CAN, called socketCan. Presumably, this kernel module should be included in Alpine, preferably as a downloadable package.
If need be I can assist in testing and further specification. We use Alpine in our in-house developed control system for Scandinavian fuel trucks. Please note that I am no expert in CAN, but I do have a variety of CAN hardware available. :)
Regarding CAN bus protocol types
In our case, we only use the CAN_RAW
protocol. However, the CAN_BCM
and CAN_ISOTP
protocol may also be nice to support as well for completeness.
We would argue that all other CAN protocols in the PF_CAN
family should not be supported since these are specific to non-standard products from a few select vendors.
Sample Test code
Below is a simple C++ test program that uses the slcan0
serial can socket. You may need an actual CAN device to run it though.
#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <iostream>
#include <cstring>
#include <unistd.h>
int main(int argc, char** argv) {
int s;
struct sockaddr_can addr{};
struct can_frame frame{};
struct ifreq ifr{};
const char *ifname = "slcan0";
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
perror("Error while opening socket");
return -1;
}
strcpy(ifr.ifr_name, ifname);
ioctl(s, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
printf("%s at index %d\n", ifname, ifr.ifr_ifindex);
if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
perror("Error in socket bind");
return -1;
}
// Example code for writing to the canbus
// frame.can_id = 0x123;
// frame.can_dlc = 2;
// frame.data[0] = 0x11;
// frame.data[1] = 0x22;
// int num_bytes = write(s, &frame, sizeof(struct can_frame));
int cnt = 0;
for (;;) {
auto v = read(s, &frame, sizeof(struct can_frame));
printf("%d v: %zi | frame: %#x - %dx%dx%dx%dx%dx%dx%dx%d", cnt++, v, frame.can_id,
frame.data[0], frame.data[1], frame.data[2], frame.data[3],
frame.data[4], frame.data[5], frame.data[6], frame.data[7]);
std::cout.flush(); // Flush this thing.
cnt = cnt % 255; // Reset the counter when we reach 255.
}
close(s);
return 0;
}