@@ -1098,6 +1098,40 @@ def receive(self) -> bytes:
10981098 return header + data
10991099
11001100
1101+ class SocketCanFdTransport (Transport ):
1102+ """Linux SocketCAN transport for CAN FD. Supports max 64-byte messages.
1103+ Sends the Compost frame as payload."""
1104+
1105+ CAN_FD_HEADER = Struct ("@IBB2x" ) # SocketCAN CAN FD frame header
1106+ CAN_MTU = 16 # Classical CAN frame
1107+ CANFD_MTU = 72 # CAN FD frame
1108+
1109+ def __init__ (self , interface : str , can_id_rx : int , can_id_tx : int ) -> None :
1110+ self .socket = socket .socket (socket .AF_CAN , socket .SOCK_RAW , socket .CAN_RAW )
1111+ self .socket .setsockopt (socket .SOL_CAN_RAW , socket .CAN_RAW_FD_FRAMES , 1 )
1112+ self .socket .bind ((interface , ))
1113+ self .can_id_rx = can_id_rx
1114+ self .can_id_tx = can_id_tx
1115+
1116+ def send (self , msg : bytes ):
1117+ length = 4 + 4 * msg [0 ]
1118+ if length > 64 :
1119+ raise ValueError ("Message length exceeds 64 bytes" )
1120+ can_frame = (self .CAN_FD_HEADER .pack (self .can_id_tx , length , 0 ) + msg ).ljust (self .CANFD_MTU , b"\x00 " )
1121+ self .socket .send (can_frame )
1122+
1123+ def receive (self ) -> bytes :
1124+ while True :
1125+ cf , ancillary_data , msg_flags , addr = self .socket .recvmsg (self .CANFD_MTU )
1126+ if len (cf ) != self .CANFD_MTU :
1127+ continue # Ignore non-FD frames
1128+ can_id , length , flags = self .CAN_FD_HEADER .unpack (cf [0 :8 ])
1129+ if can_id != self .can_id_rx :
1130+ continue # Ignore frames with wrong CAN ID
1131+ assert length <= 64
1132+ return cf [8 :8 + length ]
1133+
1134+
11011135class _Session :
11021136
11031137 _TXN_MAX = 255
0 commit comments