github.com/jordan-bonecutter/can-go@v0.0.0-20230901155856-d83995b18e50/pkg/socketcan/frame.go (about)

     1  package socketcan
     2  
     3  import (
     4  	"encoding/binary"
     5  
     6  	"go.einride.tech/can"
     7  )
     8  
     9  const (
    10  	// lengthOfFrame is the length of a SocketCAN frame in bytes.
    11  	lengthOfFrame = 16
    12  	// maxLengthOfData is the max length of a SocketCAN frame payload in bytes.
    13  	maxLengthOfData = 8
    14  	// indexOfID is the index of the first byte of the frame ID.
    15  	indexOfID = 0
    16  	// lengthOfID is the length of a frame ID in bytes.
    17  	lengthOfID = 4
    18  	// indexOfDataLengthCode is the index of the first byte of the frame dataLengthCode.
    19  	indexOfDataLengthCode = indexOfID + lengthOfID
    20  	// lengthOfDataLengthCode is the length of a frame dataLengthCode in bytes.
    21  	lengthOfDataLengthCode = 1
    22  	// indexOfPadding is the index of the first byte of frame padding.
    23  	indexOfPadding = indexOfDataLengthCode + lengthOfDataLengthCode
    24  	// lengthOfPadding is the length of frame padding in bytes.
    25  	lengthOfPadding = 3
    26  	// indexOfData is the index of the first byte of data in a frame.
    27  	indexOfData = indexOfPadding + lengthOfPadding
    28  )
    29  
    30  // error frame flag indices.
    31  const (
    32  	// indexOfLostArbitrationBit is the byte index of the lost arbitration bit in an error frame.
    33  	indexOfLostArbitrationBit = 0
    34  	// indexOfControllerError is the byte index of the controller error in an error frame.
    35  	indexOfControllerError = 1
    36  	// indexOfProtocolError is the byte index of the protocol error in an error frame.
    37  	indexOfProtocolError = 2
    38  	// indexOfProtocolViolationErrorLocation is the byte index of the protocol error location in an error frame.
    39  	indexOfProtocolViolationErrorLocation = 3
    40  	// indexOfTransceiverError is the byte index of the transceiver error in an error frame.
    41  	indexOfTransceiverError = 4
    42  	// indexOfControllerSpecificInformation is the starting byte of controller specific information in an error frame.
    43  	indexOfControllerSpecificInformation = 5
    44  	// LengthOfControllerSpecificInformation is the number of error frame bytes with controller-specific information.
    45  	LengthOfControllerSpecificInformation = 3
    46  )
    47  
    48  var _ [lengthOfFrame]struct{} = [indexOfData + maxLengthOfData]struct{}{}
    49  
    50  // id flags (copied from x/sys/unix).
    51  const (
    52  	idFlagExtended = 0x80000000
    53  	idFlagError    = 0x20000000
    54  	idFlagRemote   = 0x40000000
    55  	idMaskExtended = 0x1fffffff
    56  	idMaskStandard = 0x7ff
    57  )
    58  
    59  // FrameInterceptor provides a hook to intercept the transmission of a CAN frame.
    60  // The interceptor is called if and only if the frame transmission/receival is a success.
    61  type FrameInterceptor func(fr can.Frame)
    62  
    63  // frame represents a SocketCAN frame.
    64  //
    65  // The format specified in the Linux SocketCAN kernel module:
    66  //
    67  //	struct can_frame {
    68  //	        canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
    69  //	        __u8    can_dlc; /* frame payload length in byte (0 .. 8) */
    70  //	        __u8    __pad;   /* padding */
    71  //	        __u8    __res0;  /* reserved / padding */
    72  //	        __u8    __res1;  /* reserved / padding */
    73  //	        __u8    data[8] __attribute__((aligned(8)));
    74  //	};
    75  type frame struct {
    76  	// idAndFlags is the combined CAN ID and flags.
    77  	idAndFlags uint32
    78  	// dataLengthCode is the frame payload length in bytes.
    79  	dataLengthCode uint8
    80  	// padding+reserved fields
    81  	_ [3]byte
    82  	// bytes contains the frame payload.
    83  	data [8]byte
    84  }
    85  
    86  func (f *frame) unmarshalBinary(b []byte) {
    87  	_ = b[lengthOfFrame-1] // bounds check
    88  	f.idAndFlags = binary.LittleEndian.Uint32(b[indexOfID : indexOfID+lengthOfID])
    89  	f.dataLengthCode = b[indexOfDataLengthCode]
    90  	copy(f.data[:], b[indexOfData:lengthOfFrame])
    91  }
    92  
    93  func (f *frame) marshalBinary(b []byte) {
    94  	_ = b[lengthOfFrame-1] // bounds check
    95  	binary.LittleEndian.PutUint32(b[indexOfID:indexOfID+lengthOfID], f.idAndFlags)
    96  	b[indexOfDataLengthCode] = f.dataLengthCode
    97  	copy(b[indexOfData:], f.data[:])
    98  }
    99  
   100  func (f *frame) decodeFrame() can.Frame {
   101  	return can.Frame{
   102  		ID:         f.id(),
   103  		Length:     f.dataLengthCode,
   104  		Data:       f.data,
   105  		IsExtended: f.isExtended(),
   106  		IsRemote:   f.isRemote(),
   107  	}
   108  }
   109  
   110  func (f *frame) encodeFrame(cf can.Frame) {
   111  	f.idAndFlags = cf.ID
   112  	if cf.IsRemote {
   113  		f.idAndFlags |= idFlagRemote
   114  	}
   115  	if cf.IsExtended {
   116  		f.idAndFlags |= idFlagExtended
   117  	}
   118  	f.dataLengthCode = cf.Length
   119  	f.data = cf.Data
   120  }
   121  
   122  func (f *frame) isExtended() bool {
   123  	return f.idAndFlags&idFlagExtended > 0
   124  }
   125  
   126  func (f *frame) isRemote() bool {
   127  	return f.idAndFlags&idFlagRemote > 0
   128  }
   129  
   130  func (f *frame) isError() bool {
   131  	return f.idAndFlags&idFlagError > 0
   132  }
   133  
   134  func (f *frame) id() uint32 {
   135  	if f.isExtended() {
   136  		return f.idAndFlags & idMaskExtended
   137  	}
   138  	return f.idAndFlags & idMaskStandard
   139  }
   140  
   141  func (f *frame) decodeErrorFrame() ErrorFrame {
   142  	return ErrorFrame{
   143  		ErrorClass:                     f.errorClass(),
   144  		LostArbitrationBit:             f.lostArbitrationBit(),
   145  		ControllerError:                f.controllerError(),
   146  		ProtocolError:                  f.protocolError(),
   147  		ProtocolViolationErrorLocation: f.protocolErrorLocation(),
   148  		TransceiverError:               f.transceiverError(),
   149  		ControllerSpecificInformation:  f.controllerSpecificInformation(),
   150  	}
   151  }
   152  
   153  func (f *frame) errorClass() ErrorClass {
   154  	return ErrorClass(f.idAndFlags &^ idFlagError)
   155  }
   156  
   157  func (f *frame) lostArbitrationBit() uint8 {
   158  	return f.data[indexOfLostArbitrationBit]
   159  }
   160  
   161  func (f *frame) controllerError() ControllerError {
   162  	return ControllerError(f.data[indexOfControllerError])
   163  }
   164  
   165  func (f *frame) protocolError() ProtocolViolationError {
   166  	return ProtocolViolationError(f.data[indexOfProtocolError])
   167  }
   168  
   169  func (f *frame) protocolErrorLocation() ProtocolViolationErrorLocation {
   170  	return ProtocolViolationErrorLocation(f.data[indexOfProtocolViolationErrorLocation])
   171  }
   172  
   173  func (f *frame) transceiverError() TransceiverError {
   174  	return TransceiverError(f.data[indexOfTransceiverError])
   175  }
   176  
   177  func (f *frame) controllerSpecificInformation() [LengthOfControllerSpecificInformation]byte {
   178  	var ret [LengthOfControllerSpecificInformation]byte
   179  	start := indexOfControllerSpecificInformation
   180  	end := start + LengthOfControllerSpecificInformation
   181  	copy(ret[:], f.data[start:end])
   182  	return ret
   183  }