Line data Source code
1 : // Copyright 2024 Accenture. 2 : 3 : #ifndef GUARD_B44C60F5_D05E_45C2_B0E0_D94A8A2B646A 4 : #define GUARD_B44C60F5_D05E_45C2_B0E0_D94A8A2B646A 5 : 6 : #include <can/transceiver/AbstractCANTransceiver.h> 7 : #include <io/MemoryQueue.h> 8 : 9 : #include <atomic> 10 : 11 : namespace can 12 : { 13 : 14 : /** 15 : * The implementation of ICanTransceiver using Linux SocketCAN stack 16 : * 17 : * The class assumes that all its methods except write(), the constructor, and the destructor are 18 : * run in the same task context. The deviation from this can result in unobvious UBs. 19 : * The transceiver state change detection is currently not implemented, 20 : * the corresponding callback is never called. 21 : */ 22 1 : class SocketCanTransceiver final : public AbstractCANTransceiver 23 : { 24 : public: 25 : /** 26 : * The transceiver device (static) configuration 27 : * 28 : * The instance of this class is provided to SocketCanTransceiver constructor 29 : * and is kept by reference during the lifetime of the constructed object. 30 : */ 31 : struct DeviceConfig 32 : { 33 : char const* name; /// SocketCAN interface name 34 : uint8_t busId; /// currently not used 35 : }; 36 : 37 : explicit SocketCanTransceiver(DeviceConfig const& config); 38 : 39 : SocketCanTransceiver(SocketCanTransceiver const&) = delete; 40 : SocketCanTransceiver& operator=(SocketCanTransceiver const&) = delete; 41 : 42 : ICanTransceiver::ErrorCode init() final; 43 : ICanTransceiver::ErrorCode open() final; 44 : ICanTransceiver::ErrorCode open(CANFrame const& frame) final; 45 : ICanTransceiver::ErrorCode close() final; 46 : void shutdown() final; 47 : 48 : ICanTransceiver::ErrorCode write(CANFrame const& frame) final; 49 : ICanTransceiver::ErrorCode write(CANFrame const& frame, ICANFrameSentListener& listener) final; 50 : 51 : ICanTransceiver::ErrorCode mute() final; 52 : ICanTransceiver::ErrorCode unmute() final; 53 : 54 : uint32_t getBaudrate() const final; 55 : uint16_t getHwQueueTimeout() const final; 56 : 57 : /** 58 : * This function is supposed to be run periodically. 59 : * The callbacks registered with the ICanTransceiver will be triggered from inside this call. 60 : */ 61 : void run(int maxSentPerRun, int maxReceivedPerRun); 62 : 63 : private: 64 : static size_t const TX_QUEUE_SIZE_BYTES = 512; 65 : 66 0 : struct FrameWithListener 67 : { 68 : CANFrame frame; 69 : ICANFrameSentListener* listener; 70 : }; 71 : 72 : using TxQueue = ::io::MemoryQueue<TX_QUEUE_SIZE_BYTES, sizeof(FrameWithListener)>; 73 : 74 : // these functions are making system calls and shall be signal-masked 75 : void guardedOpen(); 76 : void guardedClose(); 77 : void guardedRun(int maxSentPerRun, int maxReceivedPerRun); 78 : 79 : TxQueue _txQueue; 80 : ::io::MemoryQueueReader<TxQueue> _txReader; 81 : ::io::MemoryQueueWriter<TxQueue> _txWriter; 82 : 83 : DeviceConfig const& _config; 84 : 85 : int _fileDescriptor; 86 : 87 : ::std::atomic_bool _writable; 88 : }; 89 : 90 : } // namespace can 91 : 92 : #endif // GUARD_B44C60F5_D05E_45C2_B0E0_D94A8A2B646A