Programming¶
CAN Programming¶
CAN Sockets …
Packet switching ⟶ much like UDP on the Internet
New protocol family:
PF_CAN
No addresses ⟶ binding by interface index
Fixed size packets (frames)
CAN in C - Socket, Interface Index¶
From Documentation/networking/can.txt
int s;
struct sockaddr_can addr;
struct ifreq ifr;
s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
strcpy(ifr.ifr_name, "can0");
ioctl(s, SIOCGIFINDEX, &ifr);
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
bind(s, (struct sockaddr *)&addr, sizeof(addr));
CAN in Python - Socket, Interface Index¶
import socket
can_socket = socket.socket(socket.PF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
can_socket.bind(('can0',))
CAN in C - Frames (1)¶
Kernel accepts (write()/send()
) and delivers (read()/recv()
)
fixed size network packtes ⟶ CAN frames
#include <linux/can.h>
struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* frame payload length */
__u8 data[8] __attribute__((aligned(8)));
};
CAN in C - Frames (2)¶
#include <linux/can.h>
struct can_frame frame;
read(s, &frame, sizeof(struct can_frame));
/* do something with frame */
write(s, &frame, sizeof(struct can_frame));
CAN in Python - Frames¶
struct can_frame {
canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
__u8 can_dlc; /* frame payload length */
__u8 data[8] __attribute__((aligned(8)));
};
import struct
frame_layout = "=IB3x8s"
frame_size = struct.calcsize(frame_layout)
frame = can_socket.recv(frame_size)
can_id, can_dlc, data = struct.unpack(frame_layout, frame)
# do something with frame
frame = struct.pack(frame_layout, can_id+1, len(data), data)
can_socket.send(frame)
What Else?¶
Interface Index
0
(Python: empty interface name ⟶ all interfaces)Alternative system calls:
recvfrom()
andsendto()
if one wants to know the interface on which a frame is receivedThe rest is Unix
File descriptors
Event loops
⟶ well-know client/server techniques
Realtime … is a completely different story
Can be done if needed
Caution: if you don’t need it don’t use it!