Socket api and CAN

Hi Folks,

I tinker around with can (the automotive protocol) on linux which basically boils down to socket can.

Intuition tells me to utilise crystals socket api but I cant open a CAN socket because I can not extend enum Socket::Family with CAN = 29_u16.

Does anyone have an idea or advice on how to approaching this?

Thanks in advance and
Since I am new to this forum: Thanks for creating that fantastic language!

TIL SocketCAN is a thing. Fascinating.

As you mentioned, you can’t add members to enums, so support for this will need to be baked into the stdlib itself — the enum at the very least should allow you to start working on an extension in your own code. If you open an issue and maybe a scratch PR, I’m sure some of the core team and/or helpful folks in the community will give you some tips along the way. There are some definitely enthusiastic contributors.

@Daniel You can create an enum with arbitrary values. You’re then responsible for making sure they have a correct value!

require "socket"

AF_CAN  = Socket::Family.new(29_u16)
CAN_RAW = Socket::Protocol.new(1)
CAN_BCM = Socket::Protocol.new(2)

raw_socket = Socket.new(AF_CAN, :raw, CAN_RAW)
bcm_socket = Socket.new(AF_CAN, :raw, CAN_BCM)
1 Like

As a generic observation to consider: when trying to add a feature in the API, it’s good to check the support in other platforms, and what should be done in those that do not support this feature.

1 Like

I wasn’t aware of that constructor which solved my issue. Thanks!

In combination with the ioctl shard I hacked a working solution for sending/receiving raw can frames in roughly 150 LoC.
I had to reopen the Socket::Address class and “overwrite” the from constructor, so that it takes my derived CanAddress into consideration.
Amazing this crystal stuff!

This is of course very Linux specific and doesn’t belong to the well designed standard lib.

4 Likes

but might be interesting to put in a shard maybe?

1 Like

to be published as a shard would require a little more efford and love…
I hacked this in the context of my job (where I have the required environment) an be trying to convince the team moving to crystal … dont know how this ends yet …

1 Like

Is it, actually? The socket implementation on Linux is based on BSD sockets. On Windows as well. The general concept should work across all these platforms. Only the concrete enum values may differ.

Sockets are generic, but AFAIK only Linux has kernel drivers which allow attaching real can bus hardware to that interface. There is also no standard for dealing with the implementation details (configuring interface, error frames etc). There is actually a whole ecosystem around in linux: GitHub - linux-can/can-utils: Linux-CAN / SocketCAN user space applications

In the windows world you usually have clumsy proprietary drivers for that while on the other unixes there is little to nothing of it (as of my knowledge).