diff --git a/README.md b/README.md index fe18922..9bbc791 100644 --- a/README.md +++ b/README.md @@ -1 +1,3 @@ # golang-socketcan + +fork from https://github.com/atuleu/golang-socketcan \ No newline at end of file diff --git a/constant.go b/constant.go deleted file mode 100644 index a18115a..0000000 --- a/constant.go +++ /dev/null @@ -1,10 +0,0 @@ -// +build !linux - -package socketcan - -const ( - CAN_EFF_MASK uint32 = 0x01ffffff - CAN_SFF_MASK uint32 = 0x000007ff - CAN_RTR_FLAG uint32 = 1 << 30 - CAN_EFF_FLAG uint32 = 1 << 31 -) diff --git a/frame.go b/frame.go index 19e8200..7502571 100644 --- a/frame.go +++ b/frame.go @@ -12,10 +12,12 @@ type CanFrame struct { func (f CanFrame) putID(buf []byte) { if f.Extended == true { - f.ID = f.ID & CAN_EFF_MASK + f.ID &= CAN_EFF_MASK + f.ID |= CAN_EFF_FLAG } else { - f.ID = f.ID & CAN_SFF_MASK + f.ID &= CAN_SFF_MASK } + if f.RTR { f.ID |= CAN_RTR_FLAG } diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..dc346a1 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module socketcan + +go 1.18 + +require golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..975cf95 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e h1:NHvCuwuS43lGnYhten69ZWqi2QOj/CiDNcKbVqwVoew= +golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/interface.go b/interface.go deleted file mode 100644 index d3425c7..0000000 --- a/interface.go +++ /dev/null @@ -1,21 +0,0 @@ -package socketcan - -import ( - "time" - - "golang.org/x/sys/unix" -) - -type Interface interface { - SocketFD() int -} - -func SetRecvTimeout(i Interface, timeout time.Duration) error { - tv := unix.NsecToTimeval(timeout.Nanoseconds()) - return unix.SetsockoptTimeval(i.SocketFD(), unix.SOL_SOCKET, unix.SO_RCVTIMEO, &tv) -} - -func SetSendTimeout(i Interface, timeout time.Duration) error { - tv := unix.NsecToTimeval(timeout.Nanoseconds()) - return unix.SetsockoptTimeval(i.SocketFD(), unix.SOL_SOCKET, unix.SO_SNDTIMEO, &tv) -} diff --git a/interface_linux.go b/interface_linux.go deleted file mode 100644 index 209606b..0000000 --- a/interface_linux.go +++ /dev/null @@ -1,35 +0,0 @@ -package socketcan - -import ( - "fmt" - "unsafe" - - "golang.org/x/sys/unix" -) - -func getIfIndex(itf Interface, ifName string) (int, error) { - ifNameRaw, err := unix.ByteSliceFromString(ifName) - if err != nil { - return 0, err - } - if len(ifNameRaw) > unix.IFNAMSIZ { - return 0, fmt.Errorf("Maximum ifname length is %d characters", unix.IFNAMSIZ) - } - - type ifreq struct { - Name [unix.IFNAMSIZ]byte - Index int - } - var ifReq ifreq - fd := itf.SocketFD() - copy(ifReq.Name[:], ifNameRaw) - _, _, errno := unix.Syscall(unix.SYS_IOCTL, - uintptr(fd), - unix.SIOCGIFINDEX, - uintptr(unsafe.Pointer(&ifReq))) - if errno != 0 { - return 0, fmt.Errorf("ioctl: %v", errno) - } - - return ifReq.Index, nil -} diff --git a/raw_interface.go b/raw_interface.go deleted file mode 100644 index 7b48bf7..0000000 --- a/raw_interface.go +++ /dev/null @@ -1,7 +0,0 @@ -package socketcan - -type RawInterface interface { - Send(CanFrame) error - Receive() (CanFrame, error) - Close() error -} diff --git a/raw_interface_linux.go b/raw_interface_linux.go index bd7ffc4..0911cc9 100644 --- a/raw_interface_linux.go +++ b/raw_interface_linux.go @@ -1,44 +1,123 @@ package socketcan -import ( - "syscall" +/* +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CAN_FILTER_PASS 0x01 //过滤方式-通过 +#define CAN_FILTER_REJECT 0x02 //过滤方式-拒绝 + +int rcvFiltersSet(int canfd, const uint canId, const uint filterType) +{ + if(canfd <= 0) //canfd就不用解释了… + return -1; + + if(0 == canId){ + setsockopt(canfd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); //不需要接收任何报文 + return 0; + } + + struct can_filter rfilter; + + if(filterType & CAN_FILTER_PASS){ + rfilter.can_id = canId; + } else { + rfilter.can_id = canId | CAN_INV_FILTER; + } + if(canId &0x80000000) { + rfilter.can_mask = 0x1fffffff; + } else { + rfilter.can_mask = 0x7ff; + } + + if(filterType & CAN_FILTER_REJECT){ + int join_filter = 1; + setsockopt(canfd, SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS, &join_filter, sizeof(join_filter)); + } + setsockopt(canfd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter)); + return 0; +} +*/ +import "C" +import ( + "errors" "golang.org/x/sys/unix" ) -type rawInterface struct { +type RawInterface struct { fd int name string } -func (itf *rawInterface) SocketFD() int { - return itf.fd +func (itf *RawInterface) getIfIndex(ifName string) (int, error) { + ifNameRaw, err := unix.ByteSliceFromString(ifName) + if err != nil { + return 0, err + } + if len(ifNameRaw) > unix.IFNAMSIZ { + return 0, fmt.Errorf("Maximum ifname length is %d characters", unix.IFNAMSIZ) + } + + type ifreq struct { + Name [unix.IFNAMSIZ]byte + Index int + } + var ifReq ifreq + copy(ifReq.Name[:], ifNameRaw) + _, _, errno := unix.Syscall(unix.SYS_IOCTL, + uintptr(itf.fd), + unix.SIOCGIFINDEX, + uintptr(unsafe.Pointer(&ifReq))) + if errno != 0 { + return 0, fmt.Errorf("ioctl: %v", errno) + } + + return ifReq.Index, nil } -func NewRawInterface(ifName string) (RawInterface, error) { - res := &rawInterface{name: ifName} +func NewCanItf(ifName string) (RawInterface, error) { + itf := RawInterface{name: ifName} var err error - res.fd, err = unix.Socket(unix.AF_CAN, unix.SOCK_RAW, unix.CAN_RAW) + itf.fd, err = unix.Socket(unix.AF_CAN, unix.SOCK_RAW, unix.CAN_RAW) if err != nil { return nil, err } - ifIndex, err := getIfIndex(res, ifName) + ifIndex, err := getIfIndex(itf, ifName) if err != nil { - return res, err + return itf, err } addr := &unix.SockaddrCAN{Ifindex: ifIndex} - err = unix.Bind(res.fd, addr) + err = unix.Bind(itf.fd, addr) - return res, err + return itf, err } -func (itf *rawInterface) Close() error { +func (itf *RawInterface) Close() error { return unix.Close(itf.fd) } -func (itf *rawInterface) Send(f CanFrame) error { +func (itf *RawInterface) Send(f CanFrame) error { frameBytes := make([]byte, 16) f.putID(frameBytes) frameBytes[4] = f.Dlc @@ -47,7 +126,7 @@ func (itf *rawInterface) Send(f CanFrame) error { return err } -func (itf *rawInterface) Receive() (CanFrame, error) { +func (itf *RawInterface) Receive() (CanFrame, error) { f := CanFrame{Data: make([]byte, 8)} frameBytes := make([]byte, 16) _, err := unix.Read(itf.fd, frameBytes) @@ -62,10 +141,11 @@ func (itf *rawInterface) Receive() (CanFrame, error) { return f, nil } -func IsClosedInterfaceError(err error) bool { - errno, ok := err.(syscall.Errno) - if ok == false { - return false +func (itf *RawInterface) AddfilterPass(canid_pass uint) error { + succ := C.rcvFiltersSet(C.int(itf.fd), C.uint(canid_pass), C.CAN_FILTER_PASS) + if succ == 0 { + return nil } - return errno == syscall.EBADF || errno == syscall.ENETDOWN || errno == syscall.ENODEV + + return errors.New("can filter failed") } diff --git a/raw_interface_stub.go b/raw_interface_stub.go deleted file mode 100644 index 04a6cd1..0000000 --- a/raw_interface_stub.go +++ /dev/null @@ -1,33 +0,0 @@ -// +build !linux - -package socketcan - -type rawInterfaceStub struct { -} - -func (itf *rawInterfaceStub) SocketFD() int { - return 0 -} - -func NewRawInterface(ifName string) (RawInterface, error) { - res := &rawInterfaceStub{} - return res, nil -} - -func (itf *rawInterfaceStub) Close() error { - return nil -} - -func (itf *rawInterfaceStub) Send(f CanFrame) error { - return nil -} - -func (itf *rawInterfaceStub) Receive() (CanFrame, error) { - f := CanFrame{Dlc: 0, Data: make([]byte, 8)} - select {} - return f, nil -} - -func IsClosedInterfaceError(err error) bool { - return false -}