Closed collinbrake closed 1 year ago
thanks for the PR.
IUC, this kind of mask is usually applied at the socket level:
struct can_filter rfilter[2];
rfilter[0].can_id = 0x123;
rfilter[0].can_mask = CAN_SFF_MASK;
rfilter[1].can_id = 0x200;
rfilter[1].can_mask = 0x700;
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
https://www.kernel.org/doc/html/latest/networking/can.html
perhaps a better approach would be to replicate this kind of API (with a Go-idiomatic approach), with some kind of type Filter struct { ... }
or type Options struct { ... }
?
WDYT ?
@sbinet My understanding is that filtering is a separate process from actually extracting the CAN ID from the frame. Please fill me in if that is incorrect. The kernel documentation you referenced states:
A filter matches, when:
& mask == can_id & mask
I take from that that the mask is only used to decide which frames are returned and which are discarded when recv
is called. We still need to apply the mask to get the CAN ID from the frame of bits.
Perhaps there should be an additional field in the Socket
type:
// Socket is a high-level representation of a CANBus socket.
type Socket struct {
iface *net.Interface
addr *unix.SockaddrCAN
dev device
rfilter []CanFilter
}
The CanFilter
type is defined in the sys/unix
package.
There would be an additional method of the Socket
type as well:
// ApplyFilters sets the CAN_RAW_FILTER option of the socket
func (sck *Socket) ApplyFilters(rfilter []CanFilter) error {
// sets rfilter and sets the socket filter option via unix method [SetsockoptCanRawFilter](https://cs.opensource.google/go/x/sys/+/2296e014:unix/syscall_linux.go;l=1344)
}
The rfilter field could be reused in Recv
to extract the CAN ID from the frame bits.
as you could probably tell from this package, my use of CANBUS
was relatively naïve, so I am by no means an expert :)
I'd probably err on something like that:
type Socket struct {
// ...
filters []unix.CanFilter
}
func (sck *Socket) SetFilters(fs []unix.CanFilter) error {
err := unix.SetsockoptCanRawFilter(sck.dev.fd, unix.SOL_CAN_RAW, unix.CAN_RAW_FILTER, fs)
if err != nil {
return fmt.Errorf("could not set CAN filters: %w", err)
}
sck.filters = fs
return nil
}
// // Send sends data with a CAN_frame id to the CAN bus.
func (sck *Socket) Send(msg Message) (int, error) { ... }
func (sck *Socket) Recv() (msg Message, err error) { ... }
type Message struct {
ID uint32
Data []byte
Kind Kind
}
type Kind uint32
const (
SFF Kind = iota
EFF
RTR
ERR
)
with something like:
func ExampleSend() {
sck, err := canbus.New()
err = sck.SetFilters([]unix.CanFilter{ ... })
_, err = sck.Send(canbus.Message{ID: 128, Data: []byte{0x1, 0xde, 0xad, 0xbe, 0xef}})
_, err = sck.Send(canbus.Message{ID: 128, Data: []byte{0x1, 0xde, 0xad, 0xbe, 0xef}, Kind: canbus.SFF}) // same than above
_, err = sck.Send(canbus.Message{ID: 128, Data: []byte{0x1, 0xde, 0xad, 0xbe, 0xef}, Kind: canbus.EFF})
}
what do you think ?
This pull request changes the
Send
andRecv
methods to require an additionalidMask uint32
argument.New syntax calling
Recv
to duplicate the original functionality:New syntax calling
Recv
to allow for extended (29-bit) CAN ID's: