1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Collections.Generic; 9 using Antmicro.Renode.Exceptions; 10 using Antmicro.Renode.Utilities; 11 using Antmicro.Renode.Utilities.Packets; 12 13 namespace Antmicro.Renode.Core.CAN 14 { 15 public class CANMessageFrame 16 { CANMessageFrame(uint id, byte[] data, bool extendedFormat = false, bool remoteFrame = false, bool fdFormat = false, bool bitRateSwitch = false)17 public CANMessageFrame(uint id, byte[] data, bool extendedFormat = false, bool remoteFrame = false, bool fdFormat = false, bool bitRateSwitch = false) 18 { 19 Id = id; 20 Data = data; 21 ExtendedFormat = extendedFormat; 22 RemoteFrame = remoteFrame; 23 FDFormat = fdFormat; 24 BitRateSwitch = bitRateSwitch; 25 } 26 ToString()27 public override string ToString() 28 { 29 return $"[Message: Data={DataAsHex}, Remote={RemoteFrame}, Extended={ExtendedFormat}, BitRateSwitch={BitRateSwitch}, FDFormat={FDFormat}, Id={Id}, DataLength={Data.Length}]"; 30 } 31 ToSocketCAN(bool useNetworkByteOrder)32 public byte[] ToSocketCAN(bool useNetworkByteOrder) 33 { 34 if(!FDFormat) 35 { 36 if(Data.Length > ClassicalSocketCANFrame.MaxDataLength) 37 { 38 throw new RecoverableException($"Classical frame cannot exceed {ClassicalSocketCANFrame.MaxDataLength} bytes of data"); 39 } 40 return ClassicalSocketCANFrame.FromCANMessageFrame(this).Encode(useNetworkByteOrder); 41 } 42 43 if(Data.Length > FlexibleSocketCANFrame.MaxDataLength) 44 { 45 throw new RecoverableException($"FD frame cannot exceed {FlexibleSocketCANFrame.MaxDataLength} bytes of data"); 46 } 47 return FlexibleSocketCANFrame.FromCANMessageFrame(this).Encode(useNetworkByteOrder); 48 } 49 TryFromSocketCAN(ISocketCANFrame frame, out CANMessageFrame message)50 public static bool TryFromSocketCAN(ISocketCANFrame frame, out CANMessageFrame message) 51 { 52 message = default(CANMessageFrame); 53 54 if(frame is ClassicalSocketCANFrame classicalFrame) 55 { 56 if(classicalFrame.errorMessageFrame) 57 { 58 return false; 59 } 60 61 message = new CANMessageFrame( 62 id: classicalFrame.id, 63 data: classicalFrame.data.CopyAndResize(classicalFrame.length), 64 extendedFormat: classicalFrame.extendedFrameFormat, 65 remoteFrame: classicalFrame.remoteTransmissionRequest, 66 fdFormat: false, 67 bitRateSwitch: false 68 ); 69 return true; 70 } 71 72 if(frame is FlexibleSocketCANFrame fdFrame) 73 { 74 if(fdFrame.errorMessageFrame) 75 { 76 return false; 77 } 78 79 message = new CANMessageFrame( 80 id: fdFrame.id, 81 data: fdFrame.data.CopyAndResize(fdFrame.length), 82 extendedFormat: fdFrame.extendedFrameFormat, 83 remoteFrame: fdFrame.remoteTransmissionRequest, 84 fdFormat: true, 85 bitRateSwitch: fdFrame.bitRateSwitch 86 ); 87 return true; 88 } 89 90 return false; 91 } 92 TryFromSocketCAN(IList<byte> data, out CANMessageFrame message, out int bytesUsed, bool useNetworkByteOrder)93 public static bool TryFromSocketCAN(IList<byte> data, out CANMessageFrame message, out int bytesUsed, bool useNetworkByteOrder) 94 { 95 if(data.TryDecodeAsSocketCANFrame(out var frame, useNetworkByteOrder)) 96 { 97 bytesUsed = frame.Size; 98 return TryFromSocketCAN(frame, out message); 99 } 100 101 message = default(CANMessageFrame); 102 bytesUsed = 0; 103 return false; 104 } 105 106 public string DataAsHex => Misc.PrettyPrintCollectionHex(Data); 107 108 public uint Id { get; } 109 public byte[] Data { get; } 110 public bool ExtendedFormat { get; } 111 public bool RemoteFrame { get; } 112 public bool FDFormat { get; } 113 public bool BitRateSwitch { get; } 114 } 115 } 116