github.com/blueinnovationsgroup/can-go@v0.0.0-20230518195432-d0567cda0028/pkg/socketcan/frame.go (about) 1 package socketcan 2 3 import ( 4 "encoding/binary" 5 6 "github.com/blueinnovationsgroup/can-go" 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 }